From 3ee4eff85174dfd67a285d980d22c24fada6d5b2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 3 Jun 2012 22:19:13 +0000 Subject: [PATCH 01/30] Update test-patches to work with a single patch series svn path=/dists/sid/linux/; revision=19073 --- debian/bin/test-patches | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/debian/bin/test-patches b/debian/bin/test-patches index 53e08c87a..ae3d7ebb7 100755 --- a/debian/bin/test-patches +++ b/debian/bin/test-patches @@ -56,10 +56,10 @@ if [ "${version%a~test}" = "$version" ]; then fi restrictfeature= -series="${version##*-}" -if [ "$featureset" != none ]; then - restrictfeature=" featureset=$featureset" - series="${series}-extra" +if [ "$featureset" = none ]; then + series="series-all" +else + series="series-${featureset}" fi # Copy all patches into a new directory @@ -67,10 +67,13 @@ rm -rf debian/patches/test/ mkdir debian/patches/test cp -t debian/patches/test/ "$@" -# Generate patch series for the new version ->debian/patches/series/"$series" +# Try to clean up any test patches on exit, but also do it now just in case +sed -i '/^+ test\//d' debian/patches/"$series" +trap "sed -i '/^+ test\//d' debian/patches/\"$series\"" EXIT + +# Append to patch series for patch in "$@"; do - echo "+ test/$(basename "$patch")${restrictfeature}" >>debian/patches/series/"$series" + echo "+ test/$(basename "$patch")" >>debian/patches/"$series" done # Regenerate control and included rules From c7e1baf19973a23bb15ad653aef74c0ebc024bf5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 3 Jun 2012 22:20:59 +0000 Subject: [PATCH 02/30] test-patches: Recognise the rt featureset automatically Also update the example featureset and flavour names. svn path=/dists/sid/linux/; revision=19074 --- debian/bin/test-patches | 6 +++--- debian/changelog | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/bin/test-patches b/debian/bin/test-patches index ae3d7ebb7..b687089f0 100755 --- a/debian/bin/test-patches +++ b/debian/bin/test-patches @@ -8,7 +8,7 @@ arch="$(dpkg --print-architecture)" kernelabi="$(uname -r)" ff="${kernelabi#+([^-])-@(trunk|+([0-9]))-}" if [ "x$ff" != "x$kernelabi" ]; then - flavour="${ff#@(openvz|vserver|xen)-}" + flavour="${ff#@(openvz|rt|vserver|xen)-}" if [ "x$flavour" != "x$ff" ]; then featureset="${ff%-$flavour}" else @@ -33,9 +33,9 @@ if [ $# -lt 1 ]; then echo >&2 "Usage: $0 [] ..." cat >&2 < specify the 'flavour' of kernel to build, e.g. 686 + -f specify the 'flavour' of kernel to build, e.g. 686-pae -j specify number of compiler jobs to run in parallel - -s specify an optional featureset to apply, e.g. xen + -s specify an optional featureset to apply, e.g. rt EOF exit 2 fi diff --git a/debian/changelog b/debian/changelog index 389cf6d43..92680c651 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * README.source: Update description of patch system to match current usage * linux-patch-debian: Remove; it is no longer necessary for GPL compliance and does not work with our current patch management + * test-patches: Recognise the rt featureset automatically -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 From 4b64bf84a96cdad79c2660a4978e09c85233b96e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 3 Jun 2012 22:44:01 +0000 Subject: [PATCH 03/30] Remove the patch series for featureset 'none' Make 'source_none' a symlink rather than treating 'none' like a real featureset. svn path=/dists/sid/linux/; revision=19075 --- debian/bin/gencontrol.py | 21 +++++++++++++-------- debian/patches/series-none | 1 - 2 files changed, 13 insertions(+), 9 deletions(-) delete mode 100644 debian/patches/series-none diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py index d7235c5a4..e2224e099 100755 --- a/debian/bin/gencontrol.py +++ b/debian/bin/gencontrol.py @@ -66,14 +66,19 @@ class Gencontrol(Base): def do_main_recurse(self, packages, makefile, vars, makeflags, extra): # Add featureset source rules for featureset in iter(self.config['base', ]['featuresets']): - makeflags_featureset = makeflags.copy() - makeflags_featureset['FEATURESET'] = featureset - cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" - % makeflags_featureset] - makefile.add('source_%s_real' % featureset, cmds=cmds_source) - makefile.add('source_%s' % featureset, - ['source_%s_real' % featureset]) - makefile.add('source', ['source_%s' % featureset]) + if featureset == 'none': + makefile.add('source_none_real', + cmds=['ln -s source source_none']) + makefile.add('source_none', ['source_none_real']) + else: + makeflags_featureset = makeflags.copy() + makeflags_featureset['FEATURESET'] = featureset + cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" + % makeflags_featureset] + makefile.add('source_%s_real' % featureset, cmds=cmds_source) + makefile.add('source_%s' % featureset, + ['source_%s_real' % featureset]) + makefile.add('source', ['source_%s' % featureset]) super(Gencontrol, self).do_main_recurse(packages, makefile, vars, makeflags, extra) diff --git a/debian/patches/series-none b/debian/patches/series-none deleted file mode 100644 index fe9c2dc01..000000000 --- a/debian/patches/series-none +++ /dev/null @@ -1 +0,0 @@ -# dummy file From 1e36c722c1418ad20c4b3f6c92191f8ae3ffe326 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 3 Jun 2012 22:59:24 +0000 Subject: [PATCH 04/30] Move special case for 'none' featureset to rules.real This is needed to get the proper dependency. svn path=/dists/sid/linux/; revision=19076 --- debian/bin/gencontrol.py | 21 ++++++++------------- debian/rules.real | 4 ++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py index e2224e099..d7235c5a4 100755 --- a/debian/bin/gencontrol.py +++ b/debian/bin/gencontrol.py @@ -66,19 +66,14 @@ class Gencontrol(Base): def do_main_recurse(self, packages, makefile, vars, makeflags, extra): # Add featureset source rules for featureset in iter(self.config['base', ]['featuresets']): - if featureset == 'none': - makefile.add('source_none_real', - cmds=['ln -s source source_none']) - makefile.add('source_none', ['source_none_real']) - else: - makeflags_featureset = makeflags.copy() - makeflags_featureset['FEATURESET'] = featureset - cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" - % makeflags_featureset] - makefile.add('source_%s_real' % featureset, cmds=cmds_source) - makefile.add('source_%s' % featureset, - ['source_%s_real' % featureset]) - makefile.add('source', ['source_%s' % featureset]) + makeflags_featureset = makeflags.copy() + makeflags_featureset['FEATURESET'] = featureset + cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" + % makeflags_featureset] + makefile.add('source_%s_real' % featureset, cmds=cmds_source) + makefile.add('source_%s' % featureset, + ['source_%s_real' % featureset]) + makefile.add('source', ['source_%s' % featureset]) super(Gencontrol, self).do_main_recurse(packages, makefile, vars, makeflags, extra) diff --git a/debian/rules.real b/debian/rules.real index 14557b246..0bd33bce8 100644 --- a/debian/rules.real +++ b/debian/rules.real @@ -86,8 +86,12 @@ $(STAMPS_DIR)/source_$(FEATURESET): SOURCE_DIR=$(BUILD_DIR)/source $(STAMPS_DIR)/source_$(FEATURESET): DIR=$(BUILD_DIR)/source_$(FEATURESET) $(STAMPS_DIR)/source_$(FEATURESET): $(STAMPS_DIR)/source rm -rf '$(DIR)' +ifeq ($(FEATURESET),none) + ln -s source '$(DIR)' +else cp -al '$(SOURCE_DIR)' '$(DIR)' $(patch_cmd) -f $(FEATURESET) +endif @$(stamp) $(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): CONFIG=$(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR) From 499ac43db3813f84e75320ca4cd30687edebfd67 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 3 Jun 2012 23:29:42 +0000 Subject: [PATCH 05/30] Convert patch system to quilt, except for the 'orig' patch series svn path=/dists/sid/linux/; revision=19077 --- debian/README.source | 33 +- debian/bin/check-patches.sh | 2 +- debian/bin/patch.apply | 50 --- debian/bin/test-patches | 6 +- debian/changelog | 1 + debian/patches/series-all | 534 ++++++++++++++--------------- debian/patches/series-rt | 532 ++++++++++++++-------------- debian/rules.real | 7 +- debian/templates/control.source.in | 2 +- 9 files changed, 549 insertions(+), 618 deletions(-) diff --git a/debian/README.source b/debian/README.source index 896a91e49..570353a1f 100644 --- a/debian/README.source +++ b/debian/README.source @@ -23,41 +23,20 @@ Updating the upstream source Applying patches to the Debian kernel tree ========================================== -The Debian kernel packaging uses a custom patching system: +The Debian kernel packaging uses the quilt patch system, but with +multiple series to allow for featuresets. Patches are stored below debian/patches, loosely sorted in bugfix/, features/ and debian/. Patches are in the standard kernel patch format (unified diff to be applied with patch -p1) and generally have DEP-3 headers. -The order and the selection of patches which are applied during build -time are specified in the series/ subdirectory. The series file 'base' -is used for all configurations and the series file 'base-extra' is -additionally used for optional featuresets. - -Let's look at the actual series file for 2.6.26-12: - -+ bugfix/all/net-unix-gc-fix-soft-lockups-oom-issues.patch -+ bugfix/all/inotify-watch-removal-umount-races.patch -+ bugfix/all/atm-duplicate-listen-on-socket-corrupts-the-vcc-table.patch -+ bugfix/all/ata-pata_marvell-vs-ahci.patch -+ features/sparc/video-sunxvr500-intergraph.patch - -The patches to be applied are specified relative to debian/patches -and must be preceded by a "+". The series files may be arbitrarily -documented with comments starting with "#". - -Let's now have a look at the series file for the addon kernel flavours -of 2.6.26-12: - -+ features/all/xen/dom0-fix-processor-throttling-when-pr-id-is-minus-1.patch featureset=xen - -The same syntax applies for specifing the patches, but an additional -argument is needed which specifies the featureset the patch applies to. - +The series file 'series-all' is used for all configurations and a +series file 'series-' is used for each optional +featureset. If you want to generate a source tree with all patches applied, run -make -f debian/rules source-all +make -f debian/rules source The resulting source can be found below debian/build. diff --git a/debian/bin/check-patches.sh b/debian/bin/check-patches.sh index 3a733fae3..2f18ea3b7 100755 --- a/debian/bin/check-patches.sh +++ b/debian/bin/check-patches.sh @@ -2,7 +2,7 @@ TMPDIR=$(mktemp -d) trap "rm -rf $TMPDIR" EXIT -grep -v "^#" debian/patches/series/* | awk '{if (NF >= 2) print "debian/patches/" $2}' | sort -u > $TMPDIR/used +sed '/^#/d; /^[[:space:]]*$/d; s/^[+X] //; s,^,debian/patches/,' debian/patches/series* | sort -u > $TMPDIR/used find debian/patches ! -path '*/series*' -type f -name "*.diff" -o -name "*.patch" -printf "%p\n" | sort > $TMPDIR/avail echo "Used patches" echo "==============" diff --git a/debian/bin/patch.apply b/debian/bin/patch.apply index 8fa9e3702..e69de29bb 100644 --- a/debian/bin/patch.apply +++ b/debian/bin/patch.apply @@ -1,50 +0,0 @@ -#!/usr/bin/env python - -import os, os.path, re, sys -from warnings import warn -from debian_linux.patches import PatchSeries - -def main(): - options, args = parse_options() - - if len(args) > 1: - print "Too much arguments" - return - - home = options.home - name = options.featureset or "all" - fp = file(os.path.join(home, "series-%s" % name)) - PatchSeries(name, home, fp)() - -def parse_options(): - from optparse import OptionParser - parser = OptionParser( - usage = "%prog [OPTION]... [TARGET]", - ) - parser.add_option( - '-f', '--featureset', - dest = 'featureset', - help = "featureset", - ) - parser.add_option( - '-H', '--overwrite-home', - dest = 'home', - help = "overwrite home [no default]", - ) - - options, args = parser.parse_args() - - return options, args - -if __name__ == '__main__': - def showwarning(message, category, filename, lineno, - file=sys.stderr, line=''): - file.write("Warning: %s\n" % message) - import warnings - warnings.showwarning = showwarning - try: - main() - except RuntimeError, e: - sys.stderr.write("Error: %s\n" % e) - raise SystemExit, 1 - diff --git a/debian/bin/test-patches b/debian/bin/test-patches index b687089f0..b05e45cf8 100755 --- a/debian/bin/test-patches +++ b/debian/bin/test-patches @@ -68,12 +68,12 @@ mkdir debian/patches/test cp -t debian/patches/test/ "$@" # Try to clean up any test patches on exit, but also do it now just in case -sed -i '/^+ test\//d' debian/patches/"$series" -trap "sed -i '/^+ test\//d' debian/patches/\"$series\"" EXIT +sed -i '/^test\//d' debian/patches/"$series" +trap "sed -i '/^test\//d' debian/patches/\"$series\"" EXIT # Append to patch series for patch in "$@"; do - echo "+ test/$(basename "$patch")" >>debian/patches/"$series" + echo "test/$(basename "$patch")" >>debian/patches/"$series" done # Regenerate control and included rules diff --git a/debian/changelog b/debian/changelog index 92680c651..23ea63169 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,6 +16,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * linux-patch-debian: Remove; it is no longer necessary for GPL compliance and does not work with our current patch management * test-patches: Recognise the rt featureset automatically + * Convert patch system to quilt, except for the 'orig' patch series -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/patches/series-all b/debian/patches/series-all index 1d618cacd..a57a4d24c 100644 --- a/debian/patches/series-all +++ b/debian/patches/series-all @@ -1,311 +1,311 @@ -+ debian/version.patch -+ debian/kernelvariables.patch -+ debian/doc-build-parallel.patch +debian/version.patch +debian/kernelvariables.patch +debian/doc-build-parallel.patch -+ features/all/drivers-media-dvb-usb-af9005-request_firmware.patch +features/all/drivers-media-dvb-usb-af9005-request_firmware.patch -+ features/all/sound-pci-cs46xx-request_firmware.patch +features/all/sound-pci-cs46xx-request_firmware.patch # Patches and source files from aufs3 repository, imported with # debian/patches/features/all/aufs3/gen-patch. -+ features/all/aufs3/aufs3-base.patch -+ features/all/aufs3/aufs3-standalone.patch -+ features/all/aufs3/aufs3-kbuild.patch -+ features/all/aufs3/aufs3-add.patch +features/all/aufs3/aufs3-base.patch +features/all/aufs3/aufs3-standalone.patch +features/all/aufs3/aufs3-kbuild.patch +features/all/aufs3/aufs3-add.patch # mark as staging/crap -+ features/all/aufs3/mark-as-staging.patch +features/all/aufs3/mark-as-staging.patch # fix added exports from security/device_cgroup.c -+ features/all/aufs3/aufs3-fix-export-__devcgroup_inode_permission.patch +features/all/aufs3/aufs3-fix-export-__devcgroup_inode_permission.patch -+ bugfix/ia64/hardcode-arch-script-output.patch -+ bugfix/mips/disable-advansys.patch -+ bugfix/arm/disable-scsi_acard.patch -+ debian/mips-disable-werror.patch -+ bugfix/powerpc/lpar-console.patch +bugfix/ia64/hardcode-arch-script-output.patch +bugfix/mips/disable-advansys.patch +bugfix/arm/disable-scsi_acard.patch +debian/mips-disable-werror.patch +bugfix/powerpc/lpar-console.patch -+ debian/sysrq-mask.patch +debian/sysrq-mask.patch -+ debian/arch-sh4-fix-uimage-build.patch +debian/arch-sh4-fix-uimage-build.patch -+ debian/af_802154-Disable-auto-loading-as-mitigation-against.patch -+ debian/rds-Disable-auto-loading-as-mitigation-against-local.patch -+ debian/decnet-Disable-auto-loading-as-mitigation-against-lo.patch +debian/af_802154-Disable-auto-loading-as-mitigation-against.patch +debian/rds-Disable-auto-loading-as-mitigation-against-local.patch +debian/decnet-Disable-auto-loading-as-mitigation-against-lo.patch -+ bugfix/all/dm-Deal-with-merge_bvec_fn-in-component-devices-bett.patch -+ features/all/Kbuild-kconfig-Verbose-version-of-listnewconfig.patch +bugfix/all/dm-Deal-with-merge_bvec_fn-in-component-devices-bett.patch +features/all/Kbuild-kconfig-Verbose-version-of-listnewconfig.patch -+ debian/sched-autogroup-disabled.patch +debian/sched-autogroup-disabled.patch #+ bugfix/all/rt2800-disable-powersaving-as-default.patch -+ features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch -+ debian/cgroups-Document-the-Debian-memory-resource-controll.patch -+ bugfix/ia64/nouveau-ACPI-support-is-dependent-on-X86.patch -+ features/x86/x86-Add-amilo-rfkill-driver-for-some-Fujitsu-Siemens.patch +features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch +debian/cgroups-Document-the-Debian-memory-resource-controll.patch +bugfix/ia64/nouveau-ACPI-support-is-dependent-on-X86.patch +features/x86/x86-Add-amilo-rfkill-driver-for-some-Fujitsu-Siemens.patch -+ bugfix/arm/ixp4xx_iobe.patch +bugfix/arm/ixp4xx_iobe.patch -+ debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch +debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch -+ bugfix/all/0004-media-staging-lirc_serial-Fix-bogus-error-codes.patch +bugfix/all/0004-media-staging-lirc_serial-Fix-bogus-error-codes.patch -+ features/all/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch -+ bugfix/all/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch -+ bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch -+ debian/x86-memtest-WARN-if-bad-RAM-found.patch -+ bugfix/all/snapshot-Implement-compat_ioctl.patch -+ debian/ARM-Remove-use-of-possibly-undefined-BUILD_BUG_ON-in.patch -+ bugfix/arm/ARM-ixp4xx-gpiolib-support.patch -+ bugfix/arm/ARM-topdown-mmap.patch -+ bugfix/alpha/alpha-add-io-read-write-16-32-be-functions.patch -+ features/arm/ARM-kirkwood-6282A1.patch -+ features/all/Input-ALPS-move-protocol-information-to-Documentatio.patch -+ features/all/Input-ALPS-add-protocol-version-field-in-alps_model_.patch -+ features/all/Input-ALPS-remove-assumptions-about-packet-size.patch -+ features/all/Input-ALPS-add-support-for-protocol-versions-3-and-4.patch -+ features/all/Input-ALPS-add-semi-MT-support-for-v3-protocol.patch -+ bugfix/x86/KVM-nVMX-Add-KVM_REQ_IMMEDIATE_EXIT.patch -+ bugfix/x86/KVM-nVMX-Fix-warning-causing-idt-vectoring-info-beha.patch +features/all/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch +bugfix/all/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch +bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch +debian/x86-memtest-WARN-if-bad-RAM-found.patch +bugfix/all/snapshot-Implement-compat_ioctl.patch +debian/ARM-Remove-use-of-possibly-undefined-BUILD_BUG_ON-in.patch +bugfix/arm/ARM-ixp4xx-gpiolib-support.patch +bugfix/arm/ARM-topdown-mmap.patch +bugfix/alpha/alpha-add-io-read-write-16-32-be-functions.patch +features/arm/ARM-kirkwood-6282A1.patch +features/all/Input-ALPS-move-protocol-information-to-Documentatio.patch +features/all/Input-ALPS-add-protocol-version-field-in-alps_model_.patch +features/all/Input-ALPS-remove-assumptions-about-packet-size.patch +features/all/Input-ALPS-add-support-for-protocol-versions-3-and-4.patch +features/all/Input-ALPS-add-semi-MT-support-for-v3-protocol.patch +bugfix/x86/KVM-nVMX-Add-KVM_REQ_IMMEDIATE_EXIT.patch +bugfix/x86/KVM-nVMX-Fix-warning-causing-idt-vectoring-info-beha.patch -+ features/all/hwmon-it87-Add-IT8728F-support.patch +features/all/hwmon-it87-Add-IT8728F-support.patch -+ bugfix/x86/drm-i915-do-not-enable-RC6p-on-Sandy-Bridge.patch -+ bugfix/x86/drm-i915-fix-operator-precedence-when-enabling-RC6p.patch +bugfix/x86/drm-i915-do-not-enable-RC6p-on-Sandy-Bridge.patch +bugfix/x86/drm-i915-fix-operator-precedence-when-enabling-RC6p.patch -+ features/all/fs-symlink-restrictions-on-sticky-directories.patch -+ features/all/fs-symlink-restrictions-on-sticky-directories-fix-2.patch -+ features/all/fs-hardlink-creation-restrictions.patch -+ features/all/fs-hardlink-creation-restrictions-fix.patch -+ features/all/fs-hardlink-creation-restriction-cleanup.patch -+ bugfix/all/kbuild-do-not-check-for-ancient-modutils-tools.patch +features/all/fs-symlink-restrictions-on-sticky-directories.patch +features/all/fs-symlink-restrictions-on-sticky-directories-fix-2.patch +features/all/fs-hardlink-creation-restrictions.patch +features/all/fs-hardlink-creation-restrictions-fix.patch +features/all/fs-hardlink-creation-restriction-cleanup.patch +bugfix/all/kbuild-do-not-check-for-ancient-modutils-tools.patch # Temporary, until the original change has been tested some more -+ debian/revert-CIFS-Respect-negotiated-MaxMpxCount.patch +debian/revert-CIFS-Respect-negotiated-MaxMpxCount.patch # Update all Hyper-V drivers to 3.4-rc1 (no longer staging) -+ features/x86/hyperv/0001-NLS-improve-UTF8-UTF16-string-conversion-routine.patch -+ features/x86/hyperv/0002-HID-Move-the-hid-hyperv-driver-out-of-staging.patch -+ features/x86/hyperv/0003-Staging-hv-storvsc-Use-mempools-to-allocate-struct-s.patch -+ features/x86/hyperv/0004-Staging-hv-storvsc-Cleanup-error-handling-in-the-pro.patch -+ features/x86/hyperv/0005-Staging-hv-storvsc-Fixup-the-error-when-processing-S.patch -+ features/x86/hyperv/0006-Staging-hv-storvsc-Fix-error-handling-storvsc_host_r.patch -+ features/x86/hyperv/0007-Staging-hv-storvsc-Use-the-accessor-function-shost_p.patch -+ features/x86/hyperv/0008-Staging-hv-storvsc-Use-the-unlocked-version-queuecom.patch -+ features/x86/hyperv/0009-Staging-hv-storvsc-use-the-macro-KBUILD_MODNAME.patch -+ features/x86/hyperv/0010-Staging-hv-storvsc-Get-rid-of-an-unnecessary-forward.patch -+ features/x86/hyperv/0011-Staging-hv-storvsc-Upgrade-the-vmstor-protocol-versi.patch -+ features/x86/hyperv/0012-Staging-hv-storvsc-Support-hot-add-of-scsi-disks.patch -+ features/x86/hyperv/0013-Staging-hv-storvsc-Support-hot-removing-of-scsi-devi.patch -+ features/x86/hyperv/0014-staging-hv-Use-kmemdup-rather-than-duplicating-its-i.patch -+ features/x86/hyperv/0015-Staging-hv-vmbus-Support-building-the-vmbus-driver-a.patch -+ features/x86/hyperv/0016-hv-Add-Kconfig-menu-entry.patch -+ features/x86/hyperv/0017-Staging-hv-mousevsc-Remove-the-mouse-driver-from-the.patch -+ features/x86/hyperv/0018-staging-hv-move-hv_netvsc-out-of-staging-area.patch -+ features/x86/hyperv/0019-net-hyperv-Fix-long-lines-in-netvsc.c.patch -+ features/x86/hyperv/0020-net-hyperv-Add-support-for-promiscuous-mode-setting.patch -+ features/x86/hyperv/0021-Staging-hv-storvsc-Disable-clustering.patch -+ features/x86/hyperv/0022-Staging-hv-storvsc-Cleanup-storvsc_device_alloc.patch -+ features/x86/hyperv/0023-Staging-hv-storvsc-Fix-a-bug-in-storvsc_command_comp.patch -+ features/x86/hyperv/0024-Staging-hv-storvsc-Fix-a-bug-in-copy_from_bounce_buf.patch -+ features/x86/hyperv/0025-Staging-hv-storvsc-Implement-per-device-memory-pools.patch -+ features/x86/hyperv/0026-Staging-hv-update-TODO-file.patch -+ features/x86/hyperv/0027-HID-hv_mouse-Properly-add-the-hid-device.patch -+ features/x86/hyperv/0028-Staging-hv-storvsc-Fix-a-bug-in-create_bounce_buffer.patch -+ features/x86/hyperv/0029-net-hyperv-Fix-the-stop-wake-queue-mechanism.patch -+ features/x86/hyperv/0030-Drivers-hv-Fix-a-memory-leak.patch -+ features/x86/hyperv/0031-Drivers-hv-Make-the-vmbus-driver-unloadable.patch -+ features/x86/hyperv/0032-Drivers-hv-Get-rid-of-an-unnecessary-check-in-hv.c.patch -+ features/x86/hyperv/0033-net-hyperv-Remove-unnecessary-kmap_atomic-in-netvsc-.patch -+ features/x86/hyperv/0034-net-hyperv-Add-NETVSP-protocol-version-negotiation.patch -+ features/x86/hyperv/0035-net-hyperv-Add-support-for-jumbo-frame-up-to-64KB.patch -+ features/x86/hyperv/0036-net-hyperv-fix-possible-memory-leak-in-do_set_multic.patch -+ features/x86/hyperv/0037-drivers-hv-Get-rid-of-some-unnecessary-code.patch -+ features/x86/hyperv/0038-net-hyperv-rx_bytes-should-account-the-ether-header-.patch -+ features/x86/hyperv/0039-HID-hyperv-Properly-disconnect-the-input-device.patch -+ features/x86/hyperv/0040-net-hyperv-fix-the-issue-that-large-packets-be-dropp.patch -+ features/x86/hyperv/0041-net-hyperv-Use-netif_tx_disable-instead-of-netif_sto.patch -+ features/x86/hyperv/0042-net-hyperv-Fix-the-page-buffer-when-an-RNDIS-message.patch -+ features/x86/hyperv/0043-drivers-hv-kvp-Add-cleanup-connector-defines.patch -+ features/x86/hyperv/0044-drivers-hv-kvp-Move-the-contents-of-hv_kvp.h-to-hype.patch -+ features/x86/hyperv/0045-net-hyperv-Convert-camel-cased-variables-in-rndis_fi.patch -+ features/x86/hyperv/0046-net-hyperv-Correct-the-assignment-in-netvsc_recv_cal.patch -+ features/x86/hyperv/0047-net-hyperv-Remove-the-unnecessary-memset-in-rndis_fi.patch -+ features/x86/hyperv/0048-Staging-hv-storvsc-Cleanup-some-comments.patch -+ features/x86/hyperv/0049-Staging-hv-storvsc-Cleanup-storvsc_probe.patch -+ features/x86/hyperv/0050-Staging-hv-storvsc-Cleanup-storvsc_queuecommand.patch -+ features/x86/hyperv/0051-Staging-hv-storvsc-Introduce-defines-for-srb-status-.patch -+ features/x86/hyperv/0052-Staging-hv-storvsc-Cleanup-storvsc_host_reset_handle.patch -+ features/x86/hyperv/0053-Staging-hv-storvsc-Move-and-cleanup-storvsc_remove.patch -+ features/x86/hyperv/0054-Staging-hv-storvsc-Add-a-comment-to-explain-life-cyc.patch -+ features/x86/hyperv/0055-Staging-hv-storvsc-Get-rid-of-the-on_io_completion-i.patch -+ features/x86/hyperv/0056-Staging-hv-storvsc-Rename-the-context-field-in-hv_st.patch -+ features/x86/hyperv/0057-Staging-hv-storvsc-Miscellaneous-cleanup-of-storvsc-.patch -+ features/x86/hyperv/0058-Staging-hv-storvsc-Cleanup-the-code-for-generating-p.patch -+ features/x86/hyperv/0059-Staging-hv-storvsc-Cleanup-some-protocol-related-con.patch -+ features/x86/hyperv/0060-Staging-hv-storvsc-Get-rid-of-some-unused-defines.patch -+ features/x86/hyperv/0061-Staging-hv-storvsc-Consolidate-the-request-structure.patch -+ features/x86/hyperv/0062-Staging-hv-storvsc-Consolidate-all-the-wire-protocol.patch -+ features/x86/hyperv/0063-drivers-hv-Cleanup-the-kvp-related-state-in-hyperv.h.patch -+ features/x86/hyperv/0064-tools-hv-Use-hyperv.h-to-get-the-KVP-definitions.patch -+ features/x86/hyperv/0065-drivers-hv-kvp-Cleanup-the-kernel-user-protocol.patch -+ features/x86/hyperv/0066-drivers-hv-Increase-the-number-of-VCPUs-supported-in.patch -+ features/x86/hyperv/0067-Staging-hv-storvsc-Move-the-storage-driver-out-of-th.patch -+ features/x86/hyperv/0068-net-hyperv-Use-the-built-in-macro-KBUILD_MODNAME-for.patch -+ features/x86/hyperv/0069-net-hyperv-Fix-data-corruption-in-rndis_filter_recei.patch -+ features/x86/hyperv/0070-net-hyperv-Add-support-for-vlan-trunking-from-guests.patch -+ features/x86/hyperv/0071-Drivers-hv-Add-new-message-types-to-enhance-KVP.patch -+ features/x86/hyperv/0072-net-hyperv-fix-erroneous-NETDEV_TX_BUSY-use.patch -+ features/x86/hyperv/0073-Drivers-hv-Support-the-newly-introduced-KVP-messages.patch -+ features/x86/hyperv/0074-Tools-hv-Fully-support-the-new-KVP-verbs-in-the-user.patch -+ features/x86/hyperv/0075-Tools-hv-Support-enumeration-from-all-the-pools.patch -+ features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch -+ features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch -+ features/x86/hyperv/0078-libata-add-a-host-flag-to-ignore-detected-ATA-device.patch -+ features/x86/hyperv/0079-ata_piix-defer-disks-to-the-Hyper-V-drivers-by-defau.patch +features/x86/hyperv/0001-NLS-improve-UTF8-UTF16-string-conversion-routine.patch +features/x86/hyperv/0002-HID-Move-the-hid-hyperv-driver-out-of-staging.patch +features/x86/hyperv/0003-Staging-hv-storvsc-Use-mempools-to-allocate-struct-s.patch +features/x86/hyperv/0004-Staging-hv-storvsc-Cleanup-error-handling-in-the-pro.patch +features/x86/hyperv/0005-Staging-hv-storvsc-Fixup-the-error-when-processing-S.patch +features/x86/hyperv/0006-Staging-hv-storvsc-Fix-error-handling-storvsc_host_r.patch +features/x86/hyperv/0007-Staging-hv-storvsc-Use-the-accessor-function-shost_p.patch +features/x86/hyperv/0008-Staging-hv-storvsc-Use-the-unlocked-version-queuecom.patch +features/x86/hyperv/0009-Staging-hv-storvsc-use-the-macro-KBUILD_MODNAME.patch +features/x86/hyperv/0010-Staging-hv-storvsc-Get-rid-of-an-unnecessary-forward.patch +features/x86/hyperv/0011-Staging-hv-storvsc-Upgrade-the-vmstor-protocol-versi.patch +features/x86/hyperv/0012-Staging-hv-storvsc-Support-hot-add-of-scsi-disks.patch +features/x86/hyperv/0013-Staging-hv-storvsc-Support-hot-removing-of-scsi-devi.patch +features/x86/hyperv/0014-staging-hv-Use-kmemdup-rather-than-duplicating-its-i.patch +features/x86/hyperv/0015-Staging-hv-vmbus-Support-building-the-vmbus-driver-a.patch +features/x86/hyperv/0016-hv-Add-Kconfig-menu-entry.patch +features/x86/hyperv/0017-Staging-hv-mousevsc-Remove-the-mouse-driver-from-the.patch +features/x86/hyperv/0018-staging-hv-move-hv_netvsc-out-of-staging-area.patch +features/x86/hyperv/0019-net-hyperv-Fix-long-lines-in-netvsc.c.patch +features/x86/hyperv/0020-net-hyperv-Add-support-for-promiscuous-mode-setting.patch +features/x86/hyperv/0021-Staging-hv-storvsc-Disable-clustering.patch +features/x86/hyperv/0022-Staging-hv-storvsc-Cleanup-storvsc_device_alloc.patch +features/x86/hyperv/0023-Staging-hv-storvsc-Fix-a-bug-in-storvsc_command_comp.patch +features/x86/hyperv/0024-Staging-hv-storvsc-Fix-a-bug-in-copy_from_bounce_buf.patch +features/x86/hyperv/0025-Staging-hv-storvsc-Implement-per-device-memory-pools.patch +features/x86/hyperv/0026-Staging-hv-update-TODO-file.patch +features/x86/hyperv/0027-HID-hv_mouse-Properly-add-the-hid-device.patch +features/x86/hyperv/0028-Staging-hv-storvsc-Fix-a-bug-in-create_bounce_buffer.patch +features/x86/hyperv/0029-net-hyperv-Fix-the-stop-wake-queue-mechanism.patch +features/x86/hyperv/0030-Drivers-hv-Fix-a-memory-leak.patch +features/x86/hyperv/0031-Drivers-hv-Make-the-vmbus-driver-unloadable.patch +features/x86/hyperv/0032-Drivers-hv-Get-rid-of-an-unnecessary-check-in-hv.c.patch +features/x86/hyperv/0033-net-hyperv-Remove-unnecessary-kmap_atomic-in-netvsc-.patch +features/x86/hyperv/0034-net-hyperv-Add-NETVSP-protocol-version-negotiation.patch +features/x86/hyperv/0035-net-hyperv-Add-support-for-jumbo-frame-up-to-64KB.patch +features/x86/hyperv/0036-net-hyperv-fix-possible-memory-leak-in-do_set_multic.patch +features/x86/hyperv/0037-drivers-hv-Get-rid-of-some-unnecessary-code.patch +features/x86/hyperv/0038-net-hyperv-rx_bytes-should-account-the-ether-header-.patch +features/x86/hyperv/0039-HID-hyperv-Properly-disconnect-the-input-device.patch +features/x86/hyperv/0040-net-hyperv-fix-the-issue-that-large-packets-be-dropp.patch +features/x86/hyperv/0041-net-hyperv-Use-netif_tx_disable-instead-of-netif_sto.patch +features/x86/hyperv/0042-net-hyperv-Fix-the-page-buffer-when-an-RNDIS-message.patch +features/x86/hyperv/0043-drivers-hv-kvp-Add-cleanup-connector-defines.patch +features/x86/hyperv/0044-drivers-hv-kvp-Move-the-contents-of-hv_kvp.h-to-hype.patch +features/x86/hyperv/0045-net-hyperv-Convert-camel-cased-variables-in-rndis_fi.patch +features/x86/hyperv/0046-net-hyperv-Correct-the-assignment-in-netvsc_recv_cal.patch +features/x86/hyperv/0047-net-hyperv-Remove-the-unnecessary-memset-in-rndis_fi.patch +features/x86/hyperv/0048-Staging-hv-storvsc-Cleanup-some-comments.patch +features/x86/hyperv/0049-Staging-hv-storvsc-Cleanup-storvsc_probe.patch +features/x86/hyperv/0050-Staging-hv-storvsc-Cleanup-storvsc_queuecommand.patch +features/x86/hyperv/0051-Staging-hv-storvsc-Introduce-defines-for-srb-status-.patch +features/x86/hyperv/0052-Staging-hv-storvsc-Cleanup-storvsc_host_reset_handle.patch +features/x86/hyperv/0053-Staging-hv-storvsc-Move-and-cleanup-storvsc_remove.patch +features/x86/hyperv/0054-Staging-hv-storvsc-Add-a-comment-to-explain-life-cyc.patch +features/x86/hyperv/0055-Staging-hv-storvsc-Get-rid-of-the-on_io_completion-i.patch +features/x86/hyperv/0056-Staging-hv-storvsc-Rename-the-context-field-in-hv_st.patch +features/x86/hyperv/0057-Staging-hv-storvsc-Miscellaneous-cleanup-of-storvsc-.patch +features/x86/hyperv/0058-Staging-hv-storvsc-Cleanup-the-code-for-generating-p.patch +features/x86/hyperv/0059-Staging-hv-storvsc-Cleanup-some-protocol-related-con.patch +features/x86/hyperv/0060-Staging-hv-storvsc-Get-rid-of-some-unused-defines.patch +features/x86/hyperv/0061-Staging-hv-storvsc-Consolidate-the-request-structure.patch +features/x86/hyperv/0062-Staging-hv-storvsc-Consolidate-all-the-wire-protocol.patch +features/x86/hyperv/0063-drivers-hv-Cleanup-the-kvp-related-state-in-hyperv.h.patch +features/x86/hyperv/0064-tools-hv-Use-hyperv.h-to-get-the-KVP-definitions.patch +features/x86/hyperv/0065-drivers-hv-kvp-Cleanup-the-kernel-user-protocol.patch +features/x86/hyperv/0066-drivers-hv-Increase-the-number-of-VCPUs-supported-in.patch +features/x86/hyperv/0067-Staging-hv-storvsc-Move-the-storage-driver-out-of-th.patch +features/x86/hyperv/0068-net-hyperv-Use-the-built-in-macro-KBUILD_MODNAME-for.patch +features/x86/hyperv/0069-net-hyperv-Fix-data-corruption-in-rndis_filter_recei.patch +features/x86/hyperv/0070-net-hyperv-Add-support-for-vlan-trunking-from-guests.patch +features/x86/hyperv/0071-Drivers-hv-Add-new-message-types-to-enhance-KVP.patch +features/x86/hyperv/0072-net-hyperv-fix-erroneous-NETDEV_TX_BUSY-use.patch +features/x86/hyperv/0073-Drivers-hv-Support-the-newly-introduced-KVP-messages.patch +features/x86/hyperv/0074-Tools-hv-Fully-support-the-new-KVP-verbs-in-the-user.patch +features/x86/hyperv/0075-Tools-hv-Support-enumeration-from-all-the-pools.patch +features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch +features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch +features/x86/hyperv/0078-libata-add-a-host-flag-to-ignore-detected-ATA-device.patch +features/x86/hyperv/0079-ata_piix-defer-disks-to-the-Hyper-V-drivers-by-defau.patch -+ features/x86/efi-stub/0001-x86-Add-missing-bzImage-fields-to-struct-setup_heade.patch -+ features/x86/efi-stub/0002-x86-Don-t-use-magic-strings-for-EFI-loader-signature.patch -+ features/x86/efi-stub/0003-efi.h-Add-struct-definition-for-boot-time-services.patch -+ features/x86/efi-stub/0004-efi.h-Add-efi_image_loaded_t.patch -+ features/x86/efi-stub/0005-efi.h-Add-allocation-types-for-boottime-allocate_pag.patch -+ features/x86/efi-stub/0006-efi.h-Add-graphics-protocol-guids.patch -+ features/x86/efi-stub/0007-efi.h-Add-boottime-locate_handle-search-types.patch -+ features/x86/efi-stub/0008-efi-Add-EFI-file-I-O-data-types.patch -+ features/x86/efi-stub/0009-x86-efi-EFI-boot-stub-support.patch -+ features/x86/efi-stub/0010-x86-efi-Break-up-large-initrd-reads.patch -+ features/x86/efi-stub/0011-x86-efi-Fix-pointer-math-issue-in-handle_ramdisks.patch -+ features/x86/efi-stub/0012-tools-include-Add-byteshift-headers-for-endian-acces.patch -+ features/x86/efi-stub/0013-x86-mkpiggy-Don-t-open-code-put_unaligned_le32.patch -+ features/x86/efi-stub/0014-x86-boot-Restrict-CFLAGS-for-hostprogs.patch -+ features/x86/efi-stub/0015-x86-efi-Fix-endian-issues-and-unaligned-accesses.patch -+ features/x86/efi-stub/0016-x86-boot-Correct-CFLAGS-for-hostprogs.patch -+ features/x86/efi-stub/0017-x86-efi-Add-dedicated-EFI-stub-entry-point.patch +features/x86/efi-stub/0001-x86-Add-missing-bzImage-fields-to-struct-setup_heade.patch +features/x86/efi-stub/0002-x86-Don-t-use-magic-strings-for-EFI-loader-signature.patch +features/x86/efi-stub/0003-efi.h-Add-struct-definition-for-boot-time-services.patch +features/x86/efi-stub/0004-efi.h-Add-efi_image_loaded_t.patch +features/x86/efi-stub/0005-efi.h-Add-allocation-types-for-boottime-allocate_pag.patch +features/x86/efi-stub/0006-efi.h-Add-graphics-protocol-guids.patch +features/x86/efi-stub/0007-efi.h-Add-boottime-locate_handle-search-types.patch +features/x86/efi-stub/0008-efi-Add-EFI-file-I-O-data-types.patch +features/x86/efi-stub/0009-x86-efi-EFI-boot-stub-support.patch +features/x86/efi-stub/0010-x86-efi-Break-up-large-initrd-reads.patch +features/x86/efi-stub/0011-x86-efi-Fix-pointer-math-issue-in-handle_ramdisks.patch +features/x86/efi-stub/0012-tools-include-Add-byteshift-headers-for-endian-acces.patch +features/x86/efi-stub/0013-x86-mkpiggy-Don-t-open-code-put_unaligned_le32.patch +features/x86/efi-stub/0014-x86-boot-Restrict-CFLAGS-for-hostprogs.patch +features/x86/efi-stub/0015-x86-efi-Fix-endian-issues-and-unaligned-accesses.patch +features/x86/efi-stub/0016-x86-boot-Correct-CFLAGS-for-hostprogs.patch +features/x86/efi-stub/0017-x86-efi-Add-dedicated-EFI-stub-entry-point.patch -+ bugfix/all/brcmsmac-INTERMEDIATE-but-not-AMPDU-only-when-tracin.patch -+ bugfix/all/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +bugfix/all/brcmsmac-INTERMEDIATE-but-not-AMPDU-only-when-tracin.patch +bugfix/all/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # Temporary, until the next ABI bump -+ debian/revert-rtc-Provide-flag-for-rtc-devices-that-don-t-s.patch -+ debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch -+ debian/efi-avoid-ABI-change.patch -+ debian/skbuff-avoid-ABI-change-in-3.2.17.patch -+ debian/usb-hcd-avoid-ABI-change-in-3.2.17.patch -+ debian/fork-avoid-ABI-change-in-3.2.18.patch -+ debian/mmc-Avoid-ABI-change-in-3.2.19.patch +debian/revert-rtc-Provide-flag-for-rtc-devices-that-don-t-s.patch +debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch +debian/efi-avoid-ABI-change.patch +debian/skbuff-avoid-ABI-change-in-3.2.17.patch +debian/usb-hcd-avoid-ABI-change-in-3.2.17.patch +debian/fork-avoid-ABI-change-in-3.2.18.patch +debian/mmc-Avoid-ABI-change-in-3.2.19.patch -+ bugfix/all/ext4-Report-max_batch_time-option-correctly.patch +bugfix/all/ext4-Report-max_batch_time-option-correctly.patch # Update wacom driver to 3.5ish -+ features/all/wacom/0001-Input-wacom-cleanup-feature-report-for-bamboos.patch -+ features/all/wacom/0002-Input-wacom-remove-unused-bamboo-HID-parsing.patch -+ features/all/wacom/0003-Input-wacom-add-some-comments-to-wacom_parse_hid.patch -+ features/all/wacom/0005-Input-wacom-read-3rd-gen-Bamboo-Touch-HID-data.patch -+ features/all/wacom/0006-Input-wacom-3rd-gen-Bamboo-P-Touch-packet-support.patch -+ features/all/wacom/0007-Input-wacom-ignore-unwanted-bamboo-packets.patch -+ features/all/wacom/0008-Input-wacom-add-support-for-Cintiq-24HD.patch -+ features/all/wacom/0009-Input-wacom-add-LED-support-for-Cintiq-24HD.patch -+ features/all/wacom/0010-Input-wacom-use-BTN_TOOL_FINGER-to-indicate-touch-de.patch -+ features/all/wacom/0011-Input-wacom-use-switch-statement-for-wacom_tpc_irq.patch -+ features/all/wacom/0012-Input-wacom-add-missing-LEDS_CLASS-to-Kconfig.patch -+ features/all/wacom/0013-Input-wacom-fix-3rd-gen-Bamboo-MT-when-4-fingers-are.patch -+ features/all/wacom/0014-Input-wacom-fix-physical-size-calculation-for-3rd-ge.patch -+ features/all/wacom/0015-Input-wacom-isolate-input-registration.patch -+ features/all/wacom/0016-Input-wacom-check-for-allocation-failure-in-probe.patch -+ features/all/wacom/0017-Input-wacom-wireless-monitor-framework.patch -+ features/all/wacom/0018-Input-wacom-create-inputs-when-wireless-connect.patch -+ features/all/wacom/0019-Input-wacom-wireless-battery-status.patch -+ features/all/wacom/0020-Input-wacom-add-basic-Intuos5-support.patch -+ features/all/wacom/0021-Input-wacom-add-Intuos5-Touch-Ring-ExpressKey-suppor.patch -+ features/all/wacom/0022-Input-wacom-add-Intuos5-Touch-Ring-LED-support.patch -+ features/all/wacom/0023-Input-wacom-add-Intuos5-multitouch-sensor-support.patch -+ features/all/wacom/0024-Input-wacom-retrieve-maximum-number-of-touch-points.patch -+ features/all/wacom/0025-Input-wacom-add-0xE5-MT-device-support.patch -+ features/all/wacom/0026-Input-wacom-return-proper-error-if-usb_get_extra_des.patch +features/all/wacom/0001-Input-wacom-cleanup-feature-report-for-bamboos.patch +features/all/wacom/0002-Input-wacom-remove-unused-bamboo-HID-parsing.patch +features/all/wacom/0003-Input-wacom-add-some-comments-to-wacom_parse_hid.patch +features/all/wacom/0005-Input-wacom-read-3rd-gen-Bamboo-Touch-HID-data.patch +features/all/wacom/0006-Input-wacom-3rd-gen-Bamboo-P-Touch-packet-support.patch +features/all/wacom/0007-Input-wacom-ignore-unwanted-bamboo-packets.patch +features/all/wacom/0008-Input-wacom-add-support-for-Cintiq-24HD.patch +features/all/wacom/0009-Input-wacom-add-LED-support-for-Cintiq-24HD.patch +features/all/wacom/0010-Input-wacom-use-BTN_TOOL_FINGER-to-indicate-touch-de.patch +features/all/wacom/0011-Input-wacom-use-switch-statement-for-wacom_tpc_irq.patch +features/all/wacom/0012-Input-wacom-add-missing-LEDS_CLASS-to-Kconfig.patch +features/all/wacom/0013-Input-wacom-fix-3rd-gen-Bamboo-MT-when-4-fingers-are.patch +features/all/wacom/0014-Input-wacom-fix-physical-size-calculation-for-3rd-ge.patch +features/all/wacom/0015-Input-wacom-isolate-input-registration.patch +features/all/wacom/0016-Input-wacom-check-for-allocation-failure-in-probe.patch +features/all/wacom/0017-Input-wacom-wireless-monitor-framework.patch +features/all/wacom/0018-Input-wacom-create-inputs-when-wireless-connect.patch +features/all/wacom/0019-Input-wacom-wireless-battery-status.patch +features/all/wacom/0020-Input-wacom-add-basic-Intuos5-support.patch +features/all/wacom/0021-Input-wacom-add-Intuos5-Touch-Ring-ExpressKey-suppor.patch +features/all/wacom/0022-Input-wacom-add-Intuos5-Touch-Ring-LED-support.patch +features/all/wacom/0023-Input-wacom-add-Intuos5-multitouch-sensor-support.patch +features/all/wacom/0024-Input-wacom-retrieve-maximum-number-of-touch-points.patch +features/all/wacom/0025-Input-wacom-add-0xE5-MT-device-support.patch +features/all/wacom/0026-Input-wacom-return-proper-error-if-usb_get_extra_des.patch # Add support for Ralink RT5392/RF5372 chipset -+ features/all/rt2x00-add-debug-message-for-new-chipset.patch -+ features/all/rt2x00-add-rt5372-chipset-support.patch +features/all/rt2x00-add-debug-message-for-new-chipset.patch +features/all/rt2x00-add-rt5372-chipset-support.patch -+ bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch +bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch # Update be2net driver to 3.5ish -+ features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch -+ features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch -+ features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch -+ features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch -+ features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch -+ features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch -+ features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch -+ features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch -+ features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch -+ features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch -+ features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch -+ features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch -+ features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch -+ features/all/be2net/0014-be2net-Use-new-hash-key.patch -+ features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch -+ features/all/be2net/0016-be2net-netpoll-support.patch -+ features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch -+ features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch -+ features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch -+ features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch -+ features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch -+ features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch -+ features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch -+ features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch -+ features/all/be2net/0025-be2net-query-link-status-in-be_open.patch -+ features/all/be2net/0026-netdev-make-net_device_ops-const.patch -+ features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch -+ features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch -+ features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch -+ features/all/be2net/0030-be2net-Fix-link-status-query-command.patch -+ features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch -+ features/all/be2net/0032-be2net-event-queue-re-design.patch -+ features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch -+ features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch -+ features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch -+ features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch -+ features/all/be2net/0037-be2net-update-driver-version.patch -+ features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch -+ features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch -+ features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch -+ features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch -+ features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch -+ features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch -+ features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch -+ features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch -+ features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch -+ features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch -+ features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch -+ features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch -+ features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch -+ features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch -+ features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch -+ features/all/be2net/0053-be2net-update-the-driver-version.patch -+ features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch -+ features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch -+ features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch -+ features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch -+ features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch +features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch +features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch +features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch +features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch +features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch +features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch +features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch +features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch +features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch +features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch +features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch +features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch +features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch +features/all/be2net/0014-be2net-Use-new-hash-key.patch +features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch +features/all/be2net/0016-be2net-netpoll-support.patch +features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch +features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch +features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch +features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch +features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch +features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch +features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch +features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch +features/all/be2net/0025-be2net-query-link-status-in-be_open.patch +features/all/be2net/0026-netdev-make-net_device_ops-const.patch +features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch +features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch +features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch +features/all/be2net/0030-be2net-Fix-link-status-query-command.patch +features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch +features/all/be2net/0032-be2net-event-queue-re-design.patch +features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch +features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch +features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch +features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch +features/all/be2net/0037-be2net-update-driver-version.patch +features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch +features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch +features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch +features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch +features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch +features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch +features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch +features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch +features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch +features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch +features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch +features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch +features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch +features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch +features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch +features/all/be2net/0053-be2net-update-the-driver-version.patch +features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch +features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch +features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch +features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch +features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch # Add CoDel from 3.5, and prerequisites -+ features/all/net-introduce-skb_flow_dissect.patch -+ features/all/flow_dissector-use-a-64bit-load-store.patch -+ features/all/net-flow_dissector.c-missing-include-linux-export.h.patch -+ features/all/codel/0001-codel-Controlled-Delay-AQM.patch -+ features/all/codel/0002-codel-use-Newton-method-instead-of-sqrt-and-divides.patch -+ features/all/codel/0003-fq_codel-Fair-Queue-Codel-AQM.patch -+ features/all/codel/0004-net-codel-Add-missing-include-linux-prefetch.h.patch -+ features/all/codel/0005-net-codel-fix-build-errors.patch -+ features/all/codel/0006-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch -+ features/all/codel/0007-fq_codel-should-use-qdisc-backlog-as-threshold.patch +features/all/net-introduce-skb_flow_dissect.patch +features/all/flow_dissector-use-a-64bit-load-store.patch +features/all/net-flow_dissector.c-missing-include-linux-export.h.patch +features/all/codel/0001-codel-Controlled-Delay-AQM.patch +features/all/codel/0002-codel-use-Newton-method-instead-of-sqrt-and-divides.patch +features/all/codel/0003-fq_codel-Fair-Queue-Codel-AQM.patch +features/all/codel/0004-net-codel-Add-missing-include-linux-prefetch.h.patch +features/all/codel/0005-net-codel-fix-build-errors.patch +features/all/codel/0006-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch +features/all/codel/0007-fq_codel-should-use-qdisc-backlog-as-threshold.patch -+ bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch +bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch # AppArmor userland compatibility. This had better be gone in wheezy+1! -+ features/all/AppArmor-compatibility-patch-for-v5-interface.patch +features/all/AppArmor-compatibility-patch-for-v5-interface.patch -+ bugfix/x86/mm-pmd_read_atomic-fix-32bit-pae-pmd-walk-vs-pmd_populate-smp-race.patch -+ bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch -+ bugfix/all/mm-fix-vma_resv_map-null-pointer.patch -+ bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch +bugfix/x86/mm-pmd_read_atomic-fix-32bit-pae-pmd-walk-vs-pmd_populate-smp-race.patch +bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch +bugfix/all/mm-fix-vma_resv_map-null-pointer.patch +bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch -+ bugfix/all/fix-scsi_wait_scan.patch +bugfix/all/fix-scsi_wait_scan.patch diff --git a/debian/patches/series-rt b/debian/patches/series-rt index a82eb4796..191f35408 100644 --- a/debian/patches/series-rt +++ b/debian/patches/series-rt @@ -1,266 +1,266 @@ -+ features/all/rt/0001-x86-Call-idle-notifier-after-irq_enter.patch -+ features/all/rt/0002-slab-lockdep-Annotate-all-slab-caches.patch -+ features/all/rt/0003-x86-kprobes-Remove-remove-bogus-preempt_enable.patch -+ features/all/rt/0004-x86-hpet-Disable-MSI-on-Lenovo-W510.patch -+ features/all/rt/0005-block-Shorten-interrupt-disabled-regions.patch -+ features/all/rt/0006-sched-Distangle-worker-accounting-from-rq-3Elock.patch -+ features/all/rt/0007-mips-enable-interrupts-in-signal.patch.patch -+ features/all/rt/0008-arm-enable-interrupts-in-signal-code.patch.patch -+ features/all/rt/0009-powerpc-85xx-Mark-cascade-irq-IRQF_NO_THREAD.patch -+ features/all/rt/0010-powerpc-wsp-Mark-opb-cascade-handler-IRQF_NO_THREAD.patch -+ features/all/rt/0011-powerpc-Mark-IPI-interrupts-IRQF_NO_THREAD.patch -+ features/all/rt/0012-powerpc-Allow-irq-threading.patch -+ features/all/rt/0013-sched-Keep-period-timer-ticking-when-throttling-acti.patch -+ features/all/rt/0014-sched-Do-not-throttle-due-to-PI-boosting.patch -+ features/all/rt/0015-time-Remove-bogus-comments.patch -+ features/all/rt/0016-x86-vdso-Remove-bogus-locking-in-update_vsyscall_tz.patch -+ features/all/rt/0017-x86-vdso-Use-seqcount-instead-of-seqlock.patch -+ features/all/rt/0018-ia64-vsyscall-Use-seqcount-instead-of-seqlock.patch -+ features/all/rt/0019-seqlock-Remove-unused-functions.patch -+ features/all/rt/0020-seqlock-Use-seqcount.patch -+ features/all/rt/0021-vfs-fs_struct-Move-code-out-of-seqcount-write-sectio.patch -+ features/all/rt/0022-timekeeping-Split-xtime_lock.patch -+ features/all/rt/0023-intel_idle-Convert-i7300_idle_lock-to-raw-spinlock.patch -+ features/all/rt/0024-mm-memcg-shorten-preempt-disabled-section-around-eve.patch -+ features/all/rt/0025-tracing-Account-for-preempt-off-in-preempt_schedule.patch -+ features/all/rt/0026-signal-revert-ptrace-preempt-magic.patch.patch -+ features/all/rt/0027-arm-Mark-pmu-interupt-IRQF_NO_THREAD.patch -+ features/all/rt/0028-arm-Allow-forced-irq-threading.patch -+ features/all/rt/0029-preempt-rt-Convert-arm-boot_lock-to-raw.patch -+ features/all/rt/0030-sched-Create-schedule_preempt_disabled.patch -+ features/all/rt/0031-sched-Use-schedule_preempt_disabled.patch -+ features/all/rt/0032-signals-Do-not-wakeup-self.patch -+ features/all/rt/0033-posix-timers-Prevent-broadcast-signals.patch -+ features/all/rt/0034-signals-Allow-rt-tasks-to-cache-one-sigqueue-struct.patch -+ features/all/rt/0035-signal-x86-Delay-calling-signals-in-atomic.patch -+ features/all/rt/0036-generic-Use-raw-local-irq-variant-for-generic-cmpxch.patch -+ features/all/rt/0037-drivers-random-Reduce-preempt-disabled-region.patch -+ features/all/rt/0038-ARM-AT91-PIT-Remove-irq-handler-when-clock-event-is-.patch -+ features/all/rt/0039-clocksource-TCLIB-Allow-higher-clock-rates-for-clock.patch -+ features/all/rt/0040-drivers-net-tulip_remove_one-needs-to-call-pci_disab.patch -+ features/all/rt/0041-drivers-net-Use-disable_irq_nosync-in-8139too.patch -+ features/all/rt/0042-drivers-net-ehea-Make-rx-irq-handler-non-threaded-IR.patch -+ features/all/rt/0043-drivers-net-at91_ether-Make-mdio-protection-rt-safe.patch -+ features/all/rt/0044-preempt-mark-legitimated-no-resched-sites.patch.patch -+ features/all/rt/0045-mm-Prepare-decoupling-the-page-fault-disabling-logic.patch -+ features/all/rt/0046-mm-Fixup-all-fault-handlers-to-check-current-pagefau.patch -+ features/all/rt/0047-mm-pagefault_disabled.patch -+ features/all/rt/0048-mm-raw_pagefault_disable.patch -+ features/all/rt/0049-filemap-fix-up.patch.patch -+ features/all/rt/0050-mm-Remove-preempt-count-from-pagefault-disable-enabl.patch -+ features/all/rt/0051-x86-highmem-Replace-BUG_ON-by-WARN_ON.patch -+ features/all/rt/0052-suspend-Prevent-might-sleep-splats.patch -+ features/all/rt/0053-OF-Fixup-resursive-locking-code-paths.patch -+ features/all/rt/0054-of-convert-devtree-lock.patch.patch -+ features/all/rt/0055-list-add-list-last-entry.patch.patch -+ features/all/rt/0056-mm-page-alloc-use-list-last-entry.patch.patch -+ features/all/rt/0057-mm-slab-move-debug-out.patch.patch -+ features/all/rt/0058-rwsem-inlcude-fix.patch.patch -+ features/all/rt/0059-sysctl-include-fix.patch.patch -+ features/all/rt/0060-net-flip-lock-dep-thingy.patch.patch -+ features/all/rt/0061-softirq-thread-do-softirq.patch.patch -+ features/all/rt/0062-softirq-split-out-code.patch.patch -+ features/all/rt/0063-x86-Do-not-unmask-io_apic-when-interrupt-is-in-progr.patch -+ features/all/rt/0064-x86-32-fix-signal-crap.patch.patch -+ features/all/rt/0065-x86-Do-not-disable-preemption-in-int3-on-32bit.patch -+ features/all/rt/0066-rcu-Reduce-lock-section.patch -+ features/all/rt/0067-locking-various-init-fixes.patch.patch -+ features/all/rt/0068-wait-Provide-__wake_up_all_locked.patch -+ features/all/rt/0069-pci-Use-__wake_up_all_locked-pci_unblock_user_cfg_ac.patch -+ features/all/rt/0070-latency-hist.patch.patch -+ features/all/rt/0071-hwlatdetect.patch.patch -+ features/all/rt/0073-early-printk-consolidate.patch.patch -+ features/all/rt/0074-printk-kill.patch.patch -+ features/all/rt/0075-printk-force_early_printk-boot-param-to-help-with-de.patch -+ features/all/rt/0076-rt-preempt-base-config.patch.patch -+ features/all/rt/0077-bug-BUG_ON-WARN_ON-variants-dependend-on-RT-RT.patch -+ features/all/rt/0078-rt-local_irq_-variants-depending-on-RT-RT.patch -+ features/all/rt/0079-preempt-Provide-preempt_-_-no-rt-variants.patch -+ features/all/rt/0080-ata-Do-not-disable-interrupts-in-ide-code-for-preemp.patch -+ features/all/rt/0081-ide-Do-not-disable-interrupts-for-PREEMPT-RT.patch -+ features/all/rt/0082-infiniband-Mellanox-IB-driver-patch-use-_nort-primit.patch -+ features/all/rt/0083-input-gameport-Do-not-disable-interrupts-on-PREEMPT_.patch -+ features/all/rt/0084-acpi-Do-not-disable-interrupts-on-PREEMPT_RT.patch -+ features/all/rt/0085-core-Do-not-disable-interrupts-on-RT-in-kernel-users.patch -+ features/all/rt/0086-core-Do-not-disable-interrupts-on-RT-in-res_counter..patch -+ features/all/rt/0087-usb-Use-local_irq_-_nort-variants.patch -+ features/all/rt/0088-tty-Do-not-disable-interrupts-in-put_ldisc-on-rt.patch -+ features/all/rt/0089-mm-scatterlist-dont-disable-irqs-on-RT.patch -+ features/all/rt/0090-signal-fix-up-rcu-wreckage.patch.patch -+ features/all/rt/0091-net-wireless-warn-nort.patch.patch -+ features/all/rt/0092-mm-Replace-cgroup_page-bit-spinlock.patch -+ features/all/rt/0093-buffer_head-Replace-bh_uptodate_lock-for-rt.patch -+ features/all/rt/0094-fs-jbd-jbd2-Make-state-lock-and-journal-head-lock-rt.patch -+ features/all/rt/0095-genirq-Disable-DEBUG_SHIRQ-for-rt.patch -+ features/all/rt/0096-genirq-Disable-random-call-on-preempt-rt.patch -+ features/all/rt/0097-genirq-disable-irqpoll-on-rt.patch -+ features/all/rt/0098-genirq-force-threading.patch.patch -+ features/all/rt/0099-drivers-net-fix-livelock-issues.patch -+ features/all/rt/0100-drivers-net-vortex-fix-locking-issues.patch -+ features/all/rt/0101-drivers-net-gianfar-Make-RT-aware.patch -+ features/all/rt/0102-USB-Fix-the-mouse-problem-when-copying-large-amounts.patch -+ features/all/rt/0103-local-var.patch.patch -+ features/all/rt/0104-rt-local-irq-lock.patch.patch -+ features/all/rt/0105-cpu-rt-variants.patch.patch -+ features/all/rt/0106-mm-slab-wrap-functions.patch.patch -+ features/all/rt/0107-slab-Fix-__do_drain-to-use-the-right-array-cache.patch -+ features/all/rt/0108-mm-More-lock-breaks-in-slab.c.patch -+ features/all/rt/0109-mm-page_alloc-rt-friendly-per-cpu-pages.patch -+ features/all/rt/0110-mm-page_alloc-reduce-lock-sections-further.patch -+ features/all/rt/0111-mm-page-alloc-fix.patch.patch -+ features/all/rt/0112-mm-convert-swap-to-percpu-locked.patch -+ features/all/rt/0113-mm-vmstat-fix-the-irq-lock-asymetry.patch.patch -+ features/all/rt/0114-mm-make-vmstat-rt-aware.patch -+ features/all/rt/0115-mm-shrink-the-page-frame-to-rt-size.patch -+ features/all/rt/0116-ARM-Initialize-ptl-lock-for-vector-page.patch -+ features/all/rt/0117-mm-Allow-only-slab-on-RT.patch -+ features/all/rt/0118-radix-tree-rt-aware.patch.patch -+ features/all/rt/0119-panic-disable-random-on-rt.patch -+ features/all/rt/0120-ipc-Make-the-ipc-code-rt-aware.patch -+ features/all/rt/0121-ipc-mqueue-Add-a-critical-section-to-avoid-a-deadloc.patch -+ features/all/rt/0122-relay-fix-timer-madness.patch -+ features/all/rt/0123-net-ipv4-route-use-locks-on-up-rt.patch.patch -+ features/all/rt/0124-workqueue-avoid-the-lock-in-cpu-dying.patch.patch -+ features/all/rt/0125-timers-prepare-for-full-preemption.patch -+ features/all/rt/0126-timers-preempt-rt-support.patch -+ features/all/rt/0127-timers-fix-timer-hotplug-on-rt.patch -+ features/all/rt/0128-timers-mov-printk_tick-to-soft-interrupt.patch -+ features/all/rt/0129-timer-delay-waking-softirqs-from-the-jiffy-tick.patch -+ features/all/rt/0130-timers-Avoid-the-switch-timers-base-set-to-NULL-tric.patch -+ features/all/rt/0131-printk-Don-t-call-printk_tick-in-printk_needs_cpu-on.patch -+ features/all/rt/0132-hrtimers-prepare-full-preemption.patch -+ features/all/rt/0133-hrtimer-fixup-hrtimer-callback-changes-for-preempt-r.patch -+ features/all/rt/0134-hrtimer-Don-t-call-the-timer-handler-from-hrtimer_st.patch -+ features/all/rt/0135-hrtimer-Add-missing-debug_activate-aid-Was-Re-ANNOUN.patch -+ features/all/rt/0136-hrtimer-fix-reprogram-madness.patch.patch -+ features/all/rt/0137-timer-fd-Prevent-live-lock.patch -+ features/all/rt/0138-posix-timers-thread-posix-cpu-timers-on-rt.patch -+ features/all/rt/0139-posix-timers-Shorten-posix_cpu_timers-CPU-kernel-thr.patch -+ features/all/rt/0140-posix-timers-Avoid-wakeups-when-no-timers-are-active.patch -+ features/all/rt/0141-sched-delay-put-task.patch.patch -+ features/all/rt/0142-sched-limit-nr-migrate.patch.patch -+ features/all/rt/0143-sched-mmdrop-delayed.patch.patch -+ features/all/rt/0144-sched-rt-mutex-wakeup.patch.patch -+ features/all/rt/0145-sched-prevent-idle-boost.patch.patch -+ features/all/rt/0146-sched-might-sleep-do-not-account-rcu-depth.patch.patch -+ features/all/rt/0147-sched-Break-out-from-load_balancing-on-rq_lock-conte.patch -+ features/all/rt/0148-sched-cond-resched.patch.patch -+ features/all/rt/0149-cond-resched-softirq-fix.patch.patch -+ features/all/rt/0150-sched-no-work-when-pi-blocked.patch.patch -+ features/all/rt/0151-cond-resched-lock-rt-tweak.patch.patch -+ features/all/rt/0152-sched-disable-ttwu-queue.patch.patch -+ features/all/rt/0153-sched-Disable-CONFIG_RT_GROUP_SCHED-on-RT.patch -+ features/all/rt/0154-sched-ttwu-Return-success-when-only-changing-the-sav.patch -+ features/all/rt/0155-stop_machine-convert-stop_machine_run-to-PREEMPT_RT.patch -+ features/all/rt/0156-stomp-machine-mark-stomper-thread.patch.patch -+ features/all/rt/0157-stomp-machine-raw-lock.patch.patch -+ features/all/rt/0158-hotplug-Lightweight-get-online-cpus.patch -+ features/all/rt/0159-hotplug-sync_unplug-No.patch -+ features/all/rt/0160-hotplug-Reread-hotplug_pcp-on-pin_current_cpu-retry.patch -+ features/all/rt/0161-sched-migrate-disable.patch.patch -+ features/all/rt/0162-hotplug-use-migrate-disable.patch.patch -+ features/all/rt/0163-hotplug-Call-cpu_unplug_begin-before-DOWN_PREPARE.patch -+ features/all/rt/0164-ftrace-migrate-disable-tracing.patch.patch -+ features/all/rt/0165-tracing-Show-padding-as-unsigned-short.patch -+ features/all/rt/0166-migrate-disable-rt-variant.patch.patch -+ features/all/rt/0167-sched-Optimize-migrate_disable.patch -+ features/all/rt/0168-sched-Generic-migrate_disable.patch -+ features/all/rt/0169-sched-rt-Fix-migrate_enable-thinko.patch -+ features/all/rt/0170-sched-teach-migrate_disable-about-atomic-contexts.patch -+ features/all/rt/0171-sched-Postpone-actual-migration-disalbe-to-schedule.patch -+ features/all/rt/0172-sched-Do-not-compare-cpu-masks-in-scheduler.patch -+ features/all/rt/0173-sched-Have-migrate_disable-ignore-bounded-threads.patch -+ features/all/rt/0174-sched-clear-pf-thread-bound-on-fallback-rq.patch.patch -+ features/all/rt/0175-ftrace-crap.patch.patch -+ features/all/rt/0176-ring-buffer-Convert-reader_lock-from-raw_spin_lock-i.patch -+ features/all/rt/0177-net-netif_rx_ni-migrate-disable.patch.patch -+ features/all/rt/0178-softirq-Sanitize-softirq-pending-for-NOHZ-RT.patch -+ features/all/rt/0179-lockdep-rt.patch.patch -+ features/all/rt/0180-mutex-no-spin-on-rt.patch.patch -+ features/all/rt/0181-softirq-local-lock.patch.patch -+ features/all/rt/0182-softirq-Export-in_serving_softirq.patch -+ features/all/rt/0183-hardirq.h-Define-softirq_count-as-OUL-to-kill-build-.patch -+ features/all/rt/0184-softirq-Fix-unplug-deadlock.patch -+ features/all/rt/0185-softirq-disable-softirq-stacks-for-rt.patch.patch -+ features/all/rt/0186-softirq-make-fifo.patch.patch -+ features/all/rt/0187-tasklet-Prevent-tasklets-from-going-into-infinite-sp.patch -+ features/all/rt/0188-genirq-Allow-disabling-of-softirq-processing-in-irq-.patch -+ features/all/rt/0189-local-vars-migrate-disable.patch.patch -+ features/all/rt/0190-md-raid5-Make-raid5_percpu-handling-RT-aware.patch -+ features/all/rt/0191-rtmutex-lock-killable.patch.patch -+ features/all/rt/0192-rtmutex-futex-prepare-rt.patch.patch -+ features/all/rt/0193-futex-Fix-bug-on-when-a-requeued-RT-task-times-out.patch -+ features/all/rt/0194-rt-mutex-add-sleeping-spinlocks-support.patch.patch -+ features/all/rt/0195-spinlock-types-separate-raw.patch.patch -+ features/all/rt/0196-rtmutex-avoid-include-hell.patch.patch -+ features/all/rt/0197-rt-add-rt-spinlocks.patch.patch -+ features/all/rt/0198-rt-add-rt-to-mutex-headers.patch.patch -+ features/all/rt/0199-rwsem-add-rt-variant.patch.patch -+ features/all/rt/0200-rt-Add-the-preempt-rt-lock-replacement-APIs.patch -+ features/all/rt/0201-rwlocks-Fix-section-mismatch.patch -+ features/all/rt/0202-timer-handle-idle-trylock-in-get-next-timer-irq.patc.patch -+ features/all/rt/0203-RCU-Force-PREEMPT_RCU-for-PREEMPT-RT.patch -+ features/all/rt/0204-rcu-Frob-softirq-test.patch -+ features/all/rt/0205-rcu-Merge-RCU-bh-into-RCU-preempt.patch -+ features/all/rt/0206-rcu-Fix-macro-substitution-for-synchronize_rcu_bh-on.patch -+ features/all/rt/0207-rcu-more-fallout.patch.patch -+ features/all/rt/0208-rcu-Make-ksoftirqd-do-RCU-quiescent-states.patch -+ features/all/rt/0209-rt-rcutree-Move-misplaced-prototype.patch -+ features/all/rt/0210-lglocks-rt.patch.patch -+ features/all/rt/0211-serial-8250-Clean-up-the-locking-for-rt.patch -+ features/all/rt/0212-serial-8250-Call-flush_to_ldisc-when-the-irq-is-thre.patch -+ features/all/rt/0213-drivers-tty-fix-omap-lock-crap.patch.patch -+ features/all/rt/0214-rt-Improve-the-serial-console-PASS_LIMIT.patch -+ features/all/rt/0215-fs-namespace-preemption-fix.patch -+ features/all/rt/0216-mm-protect-activate-switch-mm.patch.patch -+ features/all/rt/0217-fs-block-rt-support.patch.patch -+ features/all/rt/0218-fs-ntfs-disable-interrupt-only-on-RT.patch -+ features/all/rt/0219-x86-Convert-mce-timer-to-hrtimer.patch -+ features/all/rt/0220-x86-stackprotector-Avoid-random-pool-on-rt.patch -+ features/all/rt/0221-x86-Use-generic-rwsem_spinlocks-on-rt.patch -+ features/all/rt/0222-x86-Disable-IST-stacks-for-debug-int-3-stack-fault-f.patch -+ features/all/rt/0223-workqueue-use-get-cpu-light.patch.patch -+ features/all/rt/0224-epoll.patch.patch -+ features/all/rt/0225-mm-vmalloc.patch.patch -+ features/all/rt/revert-workqueue-skip-nr_running-sanity-check-in-wor.patch -+ features/all/rt/0226-workqueue-Fix-cpuhotplug-trainwreck.patch -+ features/all/rt/0227-workqueue-Fix-PF_THREAD_BOUND-abuse.patch -+ features/all/rt/0228-workqueue-Use-get_cpu_light-in-flush_gcwq.patch -+ features/all/rt/0229-hotplug-stuff.patch.patch -+ features/all/rt/0230-debugobjects-rt.patch.patch -+ features/all/rt/0231-jump-label-rt.patch.patch -+ features/all/rt/0232-skbufhead-raw-lock.patch.patch -+ features/all/rt/0233-x86-no-perf-irq-work-rt.patch.patch -+ features/all/rt/0234-console-make-rt-friendly.patch.patch -+ features/all/rt/0235-printk-Disable-migration-instead-of-preemption.patch -+ features/all/rt/0236-power-use-generic-rwsem-on-rt.patch -+ features/all/rt/0237-power-disable-highmem-on-rt.patch.patch -+ features/all/rt/0238-arm-disable-highmem-on-rt.patch.patch -+ features/all/rt/0239-ARM-at91-tclib-Default-to-tclib-timer-for-RT.patch -+ features/all/rt/0240-mips-disable-highmem-on-rt.patch.patch -+ features/all/rt/0241-net-Avoid-livelock-in-net_tx_action-on-RT.patch -+ features/all/rt/0242-ping-sysrq.patch.patch -+ features/all/rt/0243-kgdb-serial-Short-term-workaround.patch -+ features/all/rt/0244-add-sys-kernel-realtime-entry.patch -+ features/all/rt/0245-mm-rt-kmap_atomic-scheduling.patch -+ features/all/rt/0246-ipc-sem-Rework-semaphore-wakeups.patch -+ features/all/rt/0247-sysrq-Allow-immediate-Magic-SysRq-output-for-PREEMPT.patch -+ features/all/rt/0248-x86-kvm-require-const-tsc-for-rt.patch.patch -+ features/all/rt/0249-scsi-fcoe-rt-aware.patch.patch -+ features/all/rt/0250-x86-crypto-Reduce-preempt-disabled-regions.patch -+ features/all/rt/0251-dm-Make-rt-aware.patch -+ features/all/rt/0252-cpumask-Disable-CONFIG_CPUMASK_OFFSTACK-for-RT.patch -+ features/all/rt/0253-seqlock-Prevent-rt-starvation.patch -+ features/all/rt/0254-timer-Fix-hotplug-for-rt.patch -+ features/all/rt/0255-futex-rt-Fix-possible-lockup-when-taking-pi_lock-in-.patch -+ features/all/rt/0256-ring-buffer-rt-Check-for-irqs-disabled-before-grabbi.patch -+ features/all/rt/0257-sched-rt-Fix-wait_task_interactive-to-test-rt_spin_l.patch -+ features/all/rt/0258-lglock-rt-Use-non-rt-for_each_cpu-in-rt-code.patch -+ features/all/rt/0259-cpu-Make-hotplug.lock-a-sleeping-spinlock-on-RT.patch -+ features/all/rt/0260-softirq-Check-preemption-after-reenabling-interrupts.patch -+ features/all/rt/0261-rt-Introduce-cpu_chill.patch -+ features/all/rt/0262-fs-dcache-Use-cpu_chill-in-trylock-loops.patch -+ features/all/rt/0263-net-Use-cpu_chill-instead-of-cpu_relax.patch -+ features/all/rt/0264-kconfig-disable-a-few-options-rt.patch.patch -+ features/all/rt/0265-kconfig-preempt-rt-full.patch.patch -+ features/all/rt/0266-rt-Make-migrate_disable-enable-and-__rt_mutex_init-n.patch +features/all/rt/0001-x86-Call-idle-notifier-after-irq_enter.patch +features/all/rt/0002-slab-lockdep-Annotate-all-slab-caches.patch +features/all/rt/0003-x86-kprobes-Remove-remove-bogus-preempt_enable.patch +features/all/rt/0004-x86-hpet-Disable-MSI-on-Lenovo-W510.patch +features/all/rt/0005-block-Shorten-interrupt-disabled-regions.patch +features/all/rt/0006-sched-Distangle-worker-accounting-from-rq-3Elock.patch +features/all/rt/0007-mips-enable-interrupts-in-signal.patch.patch +features/all/rt/0008-arm-enable-interrupts-in-signal-code.patch.patch +features/all/rt/0009-powerpc-85xx-Mark-cascade-irq-IRQF_NO_THREAD.patch +features/all/rt/0010-powerpc-wsp-Mark-opb-cascade-handler-IRQF_NO_THREAD.patch +features/all/rt/0011-powerpc-Mark-IPI-interrupts-IRQF_NO_THREAD.patch +features/all/rt/0012-powerpc-Allow-irq-threading.patch +features/all/rt/0013-sched-Keep-period-timer-ticking-when-throttling-acti.patch +features/all/rt/0014-sched-Do-not-throttle-due-to-PI-boosting.patch +features/all/rt/0015-time-Remove-bogus-comments.patch +features/all/rt/0016-x86-vdso-Remove-bogus-locking-in-update_vsyscall_tz.patch +features/all/rt/0017-x86-vdso-Use-seqcount-instead-of-seqlock.patch +features/all/rt/0018-ia64-vsyscall-Use-seqcount-instead-of-seqlock.patch +features/all/rt/0019-seqlock-Remove-unused-functions.patch +features/all/rt/0020-seqlock-Use-seqcount.patch +features/all/rt/0021-vfs-fs_struct-Move-code-out-of-seqcount-write-sectio.patch +features/all/rt/0022-timekeeping-Split-xtime_lock.patch +features/all/rt/0023-intel_idle-Convert-i7300_idle_lock-to-raw-spinlock.patch +features/all/rt/0024-mm-memcg-shorten-preempt-disabled-section-around-eve.patch +features/all/rt/0025-tracing-Account-for-preempt-off-in-preempt_schedule.patch +features/all/rt/0026-signal-revert-ptrace-preempt-magic.patch.patch +features/all/rt/0027-arm-Mark-pmu-interupt-IRQF_NO_THREAD.patch +features/all/rt/0028-arm-Allow-forced-irq-threading.patch +features/all/rt/0029-preempt-rt-Convert-arm-boot_lock-to-raw.patch +features/all/rt/0030-sched-Create-schedule_preempt_disabled.patch +features/all/rt/0031-sched-Use-schedule_preempt_disabled.patch +features/all/rt/0032-signals-Do-not-wakeup-self.patch +features/all/rt/0033-posix-timers-Prevent-broadcast-signals.patch +features/all/rt/0034-signals-Allow-rt-tasks-to-cache-one-sigqueue-struct.patch +features/all/rt/0035-signal-x86-Delay-calling-signals-in-atomic.patch +features/all/rt/0036-generic-Use-raw-local-irq-variant-for-generic-cmpxch.patch +features/all/rt/0037-drivers-random-Reduce-preempt-disabled-region.patch +features/all/rt/0038-ARM-AT91-PIT-Remove-irq-handler-when-clock-event-is-.patch +features/all/rt/0039-clocksource-TCLIB-Allow-higher-clock-rates-for-clock.patch +features/all/rt/0040-drivers-net-tulip_remove_one-needs-to-call-pci_disab.patch +features/all/rt/0041-drivers-net-Use-disable_irq_nosync-in-8139too.patch +features/all/rt/0042-drivers-net-ehea-Make-rx-irq-handler-non-threaded-IR.patch +features/all/rt/0043-drivers-net-at91_ether-Make-mdio-protection-rt-safe.patch +features/all/rt/0044-preempt-mark-legitimated-no-resched-sites.patch.patch +features/all/rt/0045-mm-Prepare-decoupling-the-page-fault-disabling-logic.patch +features/all/rt/0046-mm-Fixup-all-fault-handlers-to-check-current-pagefau.patch +features/all/rt/0047-mm-pagefault_disabled.patch +features/all/rt/0048-mm-raw_pagefault_disable.patch +features/all/rt/0049-filemap-fix-up.patch.patch +features/all/rt/0050-mm-Remove-preempt-count-from-pagefault-disable-enabl.patch +features/all/rt/0051-x86-highmem-Replace-BUG_ON-by-WARN_ON.patch +features/all/rt/0052-suspend-Prevent-might-sleep-splats.patch +features/all/rt/0053-OF-Fixup-resursive-locking-code-paths.patch +features/all/rt/0054-of-convert-devtree-lock.patch.patch +features/all/rt/0055-list-add-list-last-entry.patch.patch +features/all/rt/0056-mm-page-alloc-use-list-last-entry.patch.patch +features/all/rt/0057-mm-slab-move-debug-out.patch.patch +features/all/rt/0058-rwsem-inlcude-fix.patch.patch +features/all/rt/0059-sysctl-include-fix.patch.patch +features/all/rt/0060-net-flip-lock-dep-thingy.patch.patch +features/all/rt/0061-softirq-thread-do-softirq.patch.patch +features/all/rt/0062-softirq-split-out-code.patch.patch +features/all/rt/0063-x86-Do-not-unmask-io_apic-when-interrupt-is-in-progr.patch +features/all/rt/0064-x86-32-fix-signal-crap.patch.patch +features/all/rt/0065-x86-Do-not-disable-preemption-in-int3-on-32bit.patch +features/all/rt/0066-rcu-Reduce-lock-section.patch +features/all/rt/0067-locking-various-init-fixes.patch.patch +features/all/rt/0068-wait-Provide-__wake_up_all_locked.patch +features/all/rt/0069-pci-Use-__wake_up_all_locked-pci_unblock_user_cfg_ac.patch +features/all/rt/0070-latency-hist.patch.patch +features/all/rt/0071-hwlatdetect.patch.patch +features/all/rt/0073-early-printk-consolidate.patch.patch +features/all/rt/0074-printk-kill.patch.patch +features/all/rt/0075-printk-force_early_printk-boot-param-to-help-with-de.patch +features/all/rt/0076-rt-preempt-base-config.patch.patch +features/all/rt/0077-bug-BUG_ON-WARN_ON-variants-dependend-on-RT-RT.patch +features/all/rt/0078-rt-local_irq_-variants-depending-on-RT-RT.patch +features/all/rt/0079-preempt-Provide-preempt_-_-no-rt-variants.patch +features/all/rt/0080-ata-Do-not-disable-interrupts-in-ide-code-for-preemp.patch +features/all/rt/0081-ide-Do-not-disable-interrupts-for-PREEMPT-RT.patch +features/all/rt/0082-infiniband-Mellanox-IB-driver-patch-use-_nort-primit.patch +features/all/rt/0083-input-gameport-Do-not-disable-interrupts-on-PREEMPT_.patch +features/all/rt/0084-acpi-Do-not-disable-interrupts-on-PREEMPT_RT.patch +features/all/rt/0085-core-Do-not-disable-interrupts-on-RT-in-kernel-users.patch +features/all/rt/0086-core-Do-not-disable-interrupts-on-RT-in-res_counter..patch +features/all/rt/0087-usb-Use-local_irq_-_nort-variants.patch +features/all/rt/0088-tty-Do-not-disable-interrupts-in-put_ldisc-on-rt.patch +features/all/rt/0089-mm-scatterlist-dont-disable-irqs-on-RT.patch +features/all/rt/0090-signal-fix-up-rcu-wreckage.patch.patch +features/all/rt/0091-net-wireless-warn-nort.patch.patch +features/all/rt/0092-mm-Replace-cgroup_page-bit-spinlock.patch +features/all/rt/0093-buffer_head-Replace-bh_uptodate_lock-for-rt.patch +features/all/rt/0094-fs-jbd-jbd2-Make-state-lock-and-journal-head-lock-rt.patch +features/all/rt/0095-genirq-Disable-DEBUG_SHIRQ-for-rt.patch +features/all/rt/0096-genirq-Disable-random-call-on-preempt-rt.patch +features/all/rt/0097-genirq-disable-irqpoll-on-rt.patch +features/all/rt/0098-genirq-force-threading.patch.patch +features/all/rt/0099-drivers-net-fix-livelock-issues.patch +features/all/rt/0100-drivers-net-vortex-fix-locking-issues.patch +features/all/rt/0101-drivers-net-gianfar-Make-RT-aware.patch +features/all/rt/0102-USB-Fix-the-mouse-problem-when-copying-large-amounts.patch +features/all/rt/0103-local-var.patch.patch +features/all/rt/0104-rt-local-irq-lock.patch.patch +features/all/rt/0105-cpu-rt-variants.patch.patch +features/all/rt/0106-mm-slab-wrap-functions.patch.patch +features/all/rt/0107-slab-Fix-__do_drain-to-use-the-right-array-cache.patch +features/all/rt/0108-mm-More-lock-breaks-in-slab.c.patch +features/all/rt/0109-mm-page_alloc-rt-friendly-per-cpu-pages.patch +features/all/rt/0110-mm-page_alloc-reduce-lock-sections-further.patch +features/all/rt/0111-mm-page-alloc-fix.patch.patch +features/all/rt/0112-mm-convert-swap-to-percpu-locked.patch +features/all/rt/0113-mm-vmstat-fix-the-irq-lock-asymetry.patch.patch +features/all/rt/0114-mm-make-vmstat-rt-aware.patch +features/all/rt/0115-mm-shrink-the-page-frame-to-rt-size.patch +features/all/rt/0116-ARM-Initialize-ptl-lock-for-vector-page.patch +features/all/rt/0117-mm-Allow-only-slab-on-RT.patch +features/all/rt/0118-radix-tree-rt-aware.patch.patch +features/all/rt/0119-panic-disable-random-on-rt.patch +features/all/rt/0120-ipc-Make-the-ipc-code-rt-aware.patch +features/all/rt/0121-ipc-mqueue-Add-a-critical-section-to-avoid-a-deadloc.patch +features/all/rt/0122-relay-fix-timer-madness.patch +features/all/rt/0123-net-ipv4-route-use-locks-on-up-rt.patch.patch +features/all/rt/0124-workqueue-avoid-the-lock-in-cpu-dying.patch.patch +features/all/rt/0125-timers-prepare-for-full-preemption.patch +features/all/rt/0126-timers-preempt-rt-support.patch +features/all/rt/0127-timers-fix-timer-hotplug-on-rt.patch +features/all/rt/0128-timers-mov-printk_tick-to-soft-interrupt.patch +features/all/rt/0129-timer-delay-waking-softirqs-from-the-jiffy-tick.patch +features/all/rt/0130-timers-Avoid-the-switch-timers-base-set-to-NULL-tric.patch +features/all/rt/0131-printk-Don-t-call-printk_tick-in-printk_needs_cpu-on.patch +features/all/rt/0132-hrtimers-prepare-full-preemption.patch +features/all/rt/0133-hrtimer-fixup-hrtimer-callback-changes-for-preempt-r.patch +features/all/rt/0134-hrtimer-Don-t-call-the-timer-handler-from-hrtimer_st.patch +features/all/rt/0135-hrtimer-Add-missing-debug_activate-aid-Was-Re-ANNOUN.patch +features/all/rt/0136-hrtimer-fix-reprogram-madness.patch.patch +features/all/rt/0137-timer-fd-Prevent-live-lock.patch +features/all/rt/0138-posix-timers-thread-posix-cpu-timers-on-rt.patch +features/all/rt/0139-posix-timers-Shorten-posix_cpu_timers-CPU-kernel-thr.patch +features/all/rt/0140-posix-timers-Avoid-wakeups-when-no-timers-are-active.patch +features/all/rt/0141-sched-delay-put-task.patch.patch +features/all/rt/0142-sched-limit-nr-migrate.patch.patch +features/all/rt/0143-sched-mmdrop-delayed.patch.patch +features/all/rt/0144-sched-rt-mutex-wakeup.patch.patch +features/all/rt/0145-sched-prevent-idle-boost.patch.patch +features/all/rt/0146-sched-might-sleep-do-not-account-rcu-depth.patch.patch +features/all/rt/0147-sched-Break-out-from-load_balancing-on-rq_lock-conte.patch +features/all/rt/0148-sched-cond-resched.patch.patch +features/all/rt/0149-cond-resched-softirq-fix.patch.patch +features/all/rt/0150-sched-no-work-when-pi-blocked.patch.patch +features/all/rt/0151-cond-resched-lock-rt-tweak.patch.patch +features/all/rt/0152-sched-disable-ttwu-queue.patch.patch +features/all/rt/0153-sched-Disable-CONFIG_RT_GROUP_SCHED-on-RT.patch +features/all/rt/0154-sched-ttwu-Return-success-when-only-changing-the-sav.patch +features/all/rt/0155-stop_machine-convert-stop_machine_run-to-PREEMPT_RT.patch +features/all/rt/0156-stomp-machine-mark-stomper-thread.patch.patch +features/all/rt/0157-stomp-machine-raw-lock.patch.patch +features/all/rt/0158-hotplug-Lightweight-get-online-cpus.patch +features/all/rt/0159-hotplug-sync_unplug-No.patch +features/all/rt/0160-hotplug-Reread-hotplug_pcp-on-pin_current_cpu-retry.patch +features/all/rt/0161-sched-migrate-disable.patch.patch +features/all/rt/0162-hotplug-use-migrate-disable.patch.patch +features/all/rt/0163-hotplug-Call-cpu_unplug_begin-before-DOWN_PREPARE.patch +features/all/rt/0164-ftrace-migrate-disable-tracing.patch.patch +features/all/rt/0165-tracing-Show-padding-as-unsigned-short.patch +features/all/rt/0166-migrate-disable-rt-variant.patch.patch +features/all/rt/0167-sched-Optimize-migrate_disable.patch +features/all/rt/0168-sched-Generic-migrate_disable.patch +features/all/rt/0169-sched-rt-Fix-migrate_enable-thinko.patch +features/all/rt/0170-sched-teach-migrate_disable-about-atomic-contexts.patch +features/all/rt/0171-sched-Postpone-actual-migration-disalbe-to-schedule.patch +features/all/rt/0172-sched-Do-not-compare-cpu-masks-in-scheduler.patch +features/all/rt/0173-sched-Have-migrate_disable-ignore-bounded-threads.patch +features/all/rt/0174-sched-clear-pf-thread-bound-on-fallback-rq.patch.patch +features/all/rt/0175-ftrace-crap.patch.patch +features/all/rt/0176-ring-buffer-Convert-reader_lock-from-raw_spin_lock-i.patch +features/all/rt/0177-net-netif_rx_ni-migrate-disable.patch.patch +features/all/rt/0178-softirq-Sanitize-softirq-pending-for-NOHZ-RT.patch +features/all/rt/0179-lockdep-rt.patch.patch +features/all/rt/0180-mutex-no-spin-on-rt.patch.patch +features/all/rt/0181-softirq-local-lock.patch.patch +features/all/rt/0182-softirq-Export-in_serving_softirq.patch +features/all/rt/0183-hardirq.h-Define-softirq_count-as-OUL-to-kill-build-.patch +features/all/rt/0184-softirq-Fix-unplug-deadlock.patch +features/all/rt/0185-softirq-disable-softirq-stacks-for-rt.patch.patch +features/all/rt/0186-softirq-make-fifo.patch.patch +features/all/rt/0187-tasklet-Prevent-tasklets-from-going-into-infinite-sp.patch +features/all/rt/0188-genirq-Allow-disabling-of-softirq-processing-in-irq-.patch +features/all/rt/0189-local-vars-migrate-disable.patch.patch +features/all/rt/0190-md-raid5-Make-raid5_percpu-handling-RT-aware.patch +features/all/rt/0191-rtmutex-lock-killable.patch.patch +features/all/rt/0192-rtmutex-futex-prepare-rt.patch.patch +features/all/rt/0193-futex-Fix-bug-on-when-a-requeued-RT-task-times-out.patch +features/all/rt/0194-rt-mutex-add-sleeping-spinlocks-support.patch.patch +features/all/rt/0195-spinlock-types-separate-raw.patch.patch +features/all/rt/0196-rtmutex-avoid-include-hell.patch.patch +features/all/rt/0197-rt-add-rt-spinlocks.patch.patch +features/all/rt/0198-rt-add-rt-to-mutex-headers.patch.patch +features/all/rt/0199-rwsem-add-rt-variant.patch.patch +features/all/rt/0200-rt-Add-the-preempt-rt-lock-replacement-APIs.patch +features/all/rt/0201-rwlocks-Fix-section-mismatch.patch +features/all/rt/0202-timer-handle-idle-trylock-in-get-next-timer-irq.patc.patch +features/all/rt/0203-RCU-Force-PREEMPT_RCU-for-PREEMPT-RT.patch +features/all/rt/0204-rcu-Frob-softirq-test.patch +features/all/rt/0205-rcu-Merge-RCU-bh-into-RCU-preempt.patch +features/all/rt/0206-rcu-Fix-macro-substitution-for-synchronize_rcu_bh-on.patch +features/all/rt/0207-rcu-more-fallout.patch.patch +features/all/rt/0208-rcu-Make-ksoftirqd-do-RCU-quiescent-states.patch +features/all/rt/0209-rt-rcutree-Move-misplaced-prototype.patch +features/all/rt/0210-lglocks-rt.patch.patch +features/all/rt/0211-serial-8250-Clean-up-the-locking-for-rt.patch +features/all/rt/0212-serial-8250-Call-flush_to_ldisc-when-the-irq-is-thre.patch +features/all/rt/0213-drivers-tty-fix-omap-lock-crap.patch.patch +features/all/rt/0214-rt-Improve-the-serial-console-PASS_LIMIT.patch +features/all/rt/0215-fs-namespace-preemption-fix.patch +features/all/rt/0216-mm-protect-activate-switch-mm.patch.patch +features/all/rt/0217-fs-block-rt-support.patch.patch +features/all/rt/0218-fs-ntfs-disable-interrupt-only-on-RT.patch +features/all/rt/0219-x86-Convert-mce-timer-to-hrtimer.patch +features/all/rt/0220-x86-stackprotector-Avoid-random-pool-on-rt.patch +features/all/rt/0221-x86-Use-generic-rwsem_spinlocks-on-rt.patch +features/all/rt/0222-x86-Disable-IST-stacks-for-debug-int-3-stack-fault-f.patch +features/all/rt/0223-workqueue-use-get-cpu-light.patch.patch +features/all/rt/0224-epoll.patch.patch +features/all/rt/0225-mm-vmalloc.patch.patch +features/all/rt/revert-workqueue-skip-nr_running-sanity-check-in-wor.patch +features/all/rt/0226-workqueue-Fix-cpuhotplug-trainwreck.patch +features/all/rt/0227-workqueue-Fix-PF_THREAD_BOUND-abuse.patch +features/all/rt/0228-workqueue-Use-get_cpu_light-in-flush_gcwq.patch +features/all/rt/0229-hotplug-stuff.patch.patch +features/all/rt/0230-debugobjects-rt.patch.patch +features/all/rt/0231-jump-label-rt.patch.patch +features/all/rt/0232-skbufhead-raw-lock.patch.patch +features/all/rt/0233-x86-no-perf-irq-work-rt.patch.patch +features/all/rt/0234-console-make-rt-friendly.patch.patch +features/all/rt/0235-printk-Disable-migration-instead-of-preemption.patch +features/all/rt/0236-power-use-generic-rwsem-on-rt.patch +features/all/rt/0237-power-disable-highmem-on-rt.patch.patch +features/all/rt/0238-arm-disable-highmem-on-rt.patch.patch +features/all/rt/0239-ARM-at91-tclib-Default-to-tclib-timer-for-RT.patch +features/all/rt/0240-mips-disable-highmem-on-rt.patch.patch +features/all/rt/0241-net-Avoid-livelock-in-net_tx_action-on-RT.patch +features/all/rt/0242-ping-sysrq.patch.patch +features/all/rt/0243-kgdb-serial-Short-term-workaround.patch +features/all/rt/0244-add-sys-kernel-realtime-entry.patch +features/all/rt/0245-mm-rt-kmap_atomic-scheduling.patch +features/all/rt/0246-ipc-sem-Rework-semaphore-wakeups.patch +features/all/rt/0247-sysrq-Allow-immediate-Magic-SysRq-output-for-PREEMPT.patch +features/all/rt/0248-x86-kvm-require-const-tsc-for-rt.patch.patch +features/all/rt/0249-scsi-fcoe-rt-aware.patch.patch +features/all/rt/0250-x86-crypto-Reduce-preempt-disabled-regions.patch +features/all/rt/0251-dm-Make-rt-aware.patch +features/all/rt/0252-cpumask-Disable-CONFIG_CPUMASK_OFFSTACK-for-RT.patch +features/all/rt/0253-seqlock-Prevent-rt-starvation.patch +features/all/rt/0254-timer-Fix-hotplug-for-rt.patch +features/all/rt/0255-futex-rt-Fix-possible-lockup-when-taking-pi_lock-in-.patch +features/all/rt/0256-ring-buffer-rt-Check-for-irqs-disabled-before-grabbi.patch +features/all/rt/0257-sched-rt-Fix-wait_task_interactive-to-test-rt_spin_l.patch +features/all/rt/0258-lglock-rt-Use-non-rt-for_each_cpu-in-rt-code.patch +features/all/rt/0259-cpu-Make-hotplug.lock-a-sleeping-spinlock-on-RT.patch +features/all/rt/0260-softirq-Check-preemption-after-reenabling-interrupts.patch +features/all/rt/0261-rt-Introduce-cpu_chill.patch +features/all/rt/0262-fs-dcache-Use-cpu_chill-in-trylock-loops.patch +features/all/rt/0263-net-Use-cpu_chill-instead-of-cpu_relax.patch +features/all/rt/0264-kconfig-disable-a-few-options-rt.patch.patch +features/all/rt/0265-kconfig-preempt-rt-full.patch.patch +features/all/rt/0266-rt-Make-migrate_disable-enable-and-__rt_mutex_init-n.patch diff --git a/debian/rules.real b/debian/rules.real index 0bd33bce8..543d5b01d 100644 --- a/debian/rules.real +++ b/debian/rules.real @@ -70,7 +70,7 @@ $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: $(STAMPS_DIR)/source rm -rf '$(DIR)' define patch_cmd -cd '$(DIR)'; python '$(CURDIR)/debian/bin/patch.apply' --overwrite-home='$(CURDIR)/debian/patches' +cd '$(DIR)' && QUILT_PATCHES='$(CURDIR)/debian/patches' QUILT_SERIES=series-$(1) quilt push --quiltrc - -a -q --fuzz=1 endef $(STAMPS_DIR)/source: SOURCE_FILES = $(filter-out debian, $(wildcard * .[^.]*)) @@ -79,7 +79,7 @@ $(STAMPS_DIR)/source: rm -rf '$(DIR)' mkdir -p '$(DIR)' cp -al $(SOURCE_FILES) '$(DIR)' - $(patch_cmd) + $(call patch_cmd,all) @$(stamp) $(STAMPS_DIR)/source_$(FEATURESET): SOURCE_DIR=$(BUILD_DIR)/source @@ -90,7 +90,8 @@ ifeq ($(FEATURESET),none) ln -s source '$(DIR)' else cp -al '$(SOURCE_DIR)' '$(DIR)' - $(patch_cmd) -f $(FEATURESET) + rm -rf '$(DIR)/.pc' + $(call patch_cmd,$(FEATURESET)) endif @$(stamp) diff --git a/debian/templates/control.source.in b/debian/templates/control.source.in index d854fcbef..2aa9f0a67 100644 --- a/debian/templates/control.source.in +++ b/debian/templates/control.source.in @@ -3,7 +3,7 @@ Priority: optional Maintainer: Debian Kernel Team Uploaders: Bastian Blank , Frederik Schüler , maximilian attems , Ben Hutchings Standards-Version: 3.9.2 -Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.83) +Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.83), quilt Build-Depends-Indep: bzip2, xmlto Vcs-Svn: svn://svn.debian.org/svn/kernel/dists/trunk/linux/ Vcs-Browser: http://anonscm.debian.org/viewvc/kernel/dists/trunk/linux/ From 9115c3af40d51debe0491523995611abba7ab697 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 4 Jun 2012 00:11:03 +0000 Subject: [PATCH 06/30] Refresh some Debian-specific patches svn path=/dists/sid/linux/; revision=19078 --- .../patches/debian/arch-sh4-fix-uimage-build.patch | 6 +++--- ...t-claim-PCI-device-IDs-also-claimed-by-brc.patch | 13 +++---------- debian/patches/debian/kernelvariables.patch | 6 +++--- debian/patches/debian/version.patch | 5 +++-- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/debian/patches/debian/arch-sh4-fix-uimage-build.patch b/debian/patches/debian/arch-sh4-fix-uimage-build.patch index 1ddc00c9e..853c11ad5 100644 --- a/debian/patches/debian/arch-sh4-fix-uimage-build.patch +++ b/debian/patches/debian/arch-sh4-fix-uimage-build.patch @@ -1,5 +1,5 @@ ---- a/arch/sh/Makefile 2009-12-03 12:51:21.000000000 +0900 -+++ b/arch/sh/Makefile 2010-02-04 15:47:57.000000000 +0900 +--- a/arch/sh/Makefile ++++ b/arch/sh/Makefile @@ -75,7 +75,6 @@ # Give the various platforms the opportunity to set default image types @@ -7,4 +7,4 @@ -defaultimage-$(CONFIG_SH_SH7785LCR) := uImage defaultimage-$(CONFIG_SH_RSK) := uImage defaultimage-$(CONFIG_SH_URQUELL) := uImage - defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux + defaultimage-$(CONFIG_SH_MIGOR) := uImage diff --git a/debian/patches/debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch b/debian/patches/debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch index b8c59c04e..845e69d2d 100644 --- a/debian/patches/debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch +++ b/debian/patches/debian/bcma-Do-not-claim-PCI-device-IDs-also-claimed-by-brc.patch @@ -12,12 +12,10 @@ Signed-off-by: Ben Hutchings drivers/net/wireless/brcm80211/Kconfig | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) -diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c -index 1b51d8b..1f43cd4 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c -@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct pci_dev *dev) - } +@@ -263,11 +263,13 @@ + #endif /* CONFIG_PM */ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { +#if !IS_ENABLED(CONFIG_BRCMSMAC) @@ -31,11 +29,9 @@ index 1b51d8b..1f43cd4 100644 { 0, }, }; MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); -diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig -index 2069fc8..d5784ee 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig -@@ -5,7 +5,6 @@ config BRCMSMAC +@@ -5,7 +5,6 @@ tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" depends on PCI depends on MAC80211 @@ -43,6 +39,3 @@ index 2069fc8..d5784ee 100644 select BRCMUTIL select FW_LOADER select CRC_CCITT --- -1.7.7.3 - diff --git a/debian/patches/debian/kernelvariables.patch b/debian/patches/debian/kernelvariables.patch index f668bdd41..437a4d634 100644 --- a/debian/patches/debian/kernelvariables.patch +++ b/debian/patches/debian/kernelvariables.patch @@ -13,8 +13,8 @@ use of $(ARCH) needs to be moved after this. --- a/Makefile +++ b/Makefile -@@ -198,46 +198,6 @@ - CROSS_COMPILE ?= +@@ -195,46 +195,6 @@ + ARCH ?= $(SUBARCH) CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) -# Architecture as present in compile.h @@ -60,7 +60,7 @@ use of $(ARCH) needs to be moved after this. KCONFIG_CONFIG ?= .config export KCONFIG_CONFIG -@@ -354,6 +314,44 @@ LDFLAGS_MODULE = +@@ -354,6 +314,44 @@ AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage diff --git a/debian/patches/debian/version.patch b/debian/patches/debian/version.patch index f61f91bf6..a88e6974c 100644 --- a/debian/patches/debian/version.patch +++ b/debian/patches/debian/version.patch @@ -22,7 +22,7 @@ the kernel version string. --- a/init/version.c +++ b/init/version.c -@@ -36,12 +36,31 @@ struct uts_namespace init_uts_ns = { +@@ -37,12 +37,31 @@ }; EXPORT_SYMBOL_GPL(init_uts_ns); @@ -59,7 +59,7 @@ the kernel version string. " (" LINUX_COMPILER ") %s\n"; --- a/scripts/mkcompile_h +++ b/scripts/mkcompile_h -@@ -73,7 +73,25 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/" +@@ -73,8 +73,26 @@ echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\" @@ -87,3 +87,4 @@ the kernel version string. + fi echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\" + ) > .tmpcompile From e5db08eb93803d7c65f842c747f818140614acee Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 4 Jun 2012 00:28:29 +0000 Subject: [PATCH 07/30] Refresh another patch that has fuzz svn path=/dists/sid/linux/; revision=19079 --- ...eneric-CPU-device-on-architectures-t.patch | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/debian/patches/bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch b/debian/patches/bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch index e5dc739b4..7af8c0fa3 100644 --- a/debian/patches/bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch +++ b/debian/patches/bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch @@ -19,7 +19,7 @@ Signed-off-by: Linus Torvalds --- --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig -@@ -8,6 +8,7 @@ config FRV +@@ -8,6 +8,7 @@ select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG @@ -29,7 +29,7 @@ Signed-off-by: Linus Torvalds bool --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig -@@ -4,6 +4,7 @@ config H8300 +@@ -4,6 +4,7 @@ select HAVE_IDE select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW @@ -39,7 +39,7 @@ Signed-off-by: Linus Torvalds string --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig -@@ -6,6 +6,7 @@ config M68K +@@ -7,6 +7,7 @@ select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS @@ -49,7 +49,7 @@ Signed-off-by: Linus Torvalds bool --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig -@@ -17,6 +17,7 @@ config MICROBLAZE +@@ -17,6 +17,7 @@ select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW @@ -59,7 +59,7 @@ Signed-off-by: Linus Torvalds def_bool n --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig -@@ -15,6 +15,7 @@ config OPENRISC +@@ -15,6 +15,7 @@ select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW select GENERIC_IOMAP @@ -69,7 +69,7 @@ Signed-off-by: Linus Torvalds def_bool y --- a/arch/score/Kconfig +++ b/arch/score/Kconfig -@@ -4,6 +4,7 @@ config SCORE +@@ -4,6 +4,7 @@ def_bool y select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW @@ -79,7 +79,7 @@ Signed-off-by: Linus Torvalds prompt "System type" --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common -@@ -8,6 +8,7 @@ config UML +@@ -8,6 +8,7 @@ default y select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW @@ -89,7 +89,7 @@ Signed-off-by: Linus Torvalds bool --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig -@@ -9,6 +9,7 @@ config XTENSA +@@ -9,6 +9,7 @@ select HAVE_IDE select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW @@ -99,7 +99,7 @@ Signed-off-by: Linus Torvalds primarily for embedded systems. These processors are both --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -172,6 +172,10 @@ config SYS_HYPERVISOR +@@ -172,6 +172,10 @@ bool default n @@ -109,7 +109,7 @@ Signed-off-by: Linus Torvalds + source "drivers/base/regmap/Kconfig" - config DMA_SHARED_BUFFER + endmenu --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -12,6 +12,7 @@ @@ -120,7 +120,7 @@ Signed-off-by: Linus Torvalds #include "base.h" -@@ -248,11 +249,29 @@ bool cpu_is_hotpluggable(unsigned cpu) +@@ -248,11 +249,29 @@ } EXPORT_SYMBOL_GPL(get_cpu_sysdev); From 3ea71bf870532cd7bfa83f07d88af3fa958c8d03 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 4 Jun 2012 21:03:50 +0000 Subject: [PATCH 08/30] Update rt check-series for conversion to quilt svn path=/dists/sid/linux/; revision=19084 --- debian/patches/features/all/rt/check-series | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/debian/patches/features/all/rt/check-series b/debian/patches/features/all/rt/check-series index 3d68e54cf..a25c5292f 100755 --- a/debian/patches/features/all/rt/check-series +++ b/debian/patches/features/all/rt/check-series @@ -1,16 +1,13 @@ #! /bin/sh -debian_series="$(mktemp)" +debian_series=debian/patches/series-rt rt_series="$(mktemp)" -trap 'rm "$debian_series" "$rt_series"' INT QUIT EXIT - -# Pick all featureset=rt patches -grep "featureset=rt$" debian/patches/series/base-extra > "$debian_series" +trap 'rm "$rt_series"' INT QUIT EXIT # Remove comments and empty lines. Drop localversion patch as uname version # shouldn't be touched. Reformat to match series format. -sed -r -e 's/ *#.*//; /^$/d; /^....-(localversion\.patch|Linux-.*-REBASE)\.patch$/d; s,.*,+ features/all/rt/& featureset=rt,' "debian/patches/features/all/rt/series" > "$rt_series" +sed -r -e 's/ *#.*//; /^$/d; /^....-(localversion\.patch|Linux-.*-REBASE)\.patch$/d; s,.*,features/all/rt/&,' "debian/patches/features/all/rt/series" > "$rt_series" # removed lines are OK if the rt patch contains fixes that are applied on # featureset=none kernels, too. From 5ba1dec55defc46905dbe0826b3eb793a95b765b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 6 Jun 2012 12:15:57 +0000 Subject: [PATCH 09/30] udeb: Build-Depend on kernel-wedge >= 2.84 This allows us to list modules as required even if they are built-in in some configurations. (Which I already did by mistake with 'hid' in 3.2.19-1.) svn path=/dists/sid/linux/; revision=19088 --- debian/changelog | 2 ++ debian/templates/control.source.in | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 23ea63169..72131cceb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,8 @@ linux (3.2.19-2) UNRELEASED; urgency=low and does not work with our current patch management * test-patches: Recognise the rt featureset automatically * Convert patch system to quilt, except for the 'orig' patch series + * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list + modules as required even if they are built-in in some configurations -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/templates/control.source.in b/debian/templates/control.source.in index 2aa9f0a67..8bc6b65e3 100644 --- a/debian/templates/control.source.in +++ b/debian/templates/control.source.in @@ -3,7 +3,7 @@ Priority: optional Maintainer: Debian Kernel Team Uploaders: Bastian Blank , Frederik Schüler , maximilian attems , Ben Hutchings Standards-Version: 3.9.2 -Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.83), quilt +Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.84), quilt Build-Depends-Indep: bzip2, xmlto Vcs-Svn: svn://svn.debian.org/svn/kernel/dists/trunk/linux/ Vcs-Browser: http://anonscm.debian.org/viewvc/kernel/dists/trunk/linux/ From dbf716c7988828eae7e5a9ea9ccba63f3e6a6d92 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 7 Jun 2012 06:09:25 +0000 Subject: [PATCH 10/30] net: Backport team driver from Linux 3.5-rc1 svn path=/dists/sid/linux/; revision=19094 --- debian/changelog | 2 + debian/config/config | 8 + .../all/define-netdev_features_t.patch | 18 + ...llow-to-create-sk-unattached-filters.patch | 120 + ...et-introduce-ethernet-teaming-device.patch | 2322 +++++++++++++++++ ...-rcu_read_lock-when-running-netlink-.patch | 49 + ...am-convert-overall-spinlock-to-mutex.patch | 149 ++ ...4-team-replicate-options-on-register.patch | 189 ++ .../all/team/0005-team-add-fix_features.patch | 54 + ...am-avoid-using-variable-length-array.patch | 50 + ...am-replace-kmalloc-memcpy-by-kmemdup.patch | 38 + ...net-treewide-use-of-RCU_INIT_POINTER.patch | 28 + ...an_vid_-add-del-and-use-them-instead.patch | 132 + ...unctions-to-do-mass-addition-deletio.patch | 81 + ...team-use-vlan_vids_-addr-del-_by_dev.patch | 53 + ...ly-changed-options-ports-via-netlink.patch | 371 +++ .../team/0013-team-Stop-using-NLA_PUT.patch | 108 + .../0014-team-add-binary-option-type.patch | 124 + .../team/0015-team-add-loadbalance-mode.patch | 241 ++ ...eam-add-support-for-per-port-options.patch | 687 +++++ .../team/0017-team-add-bool-option-type.patch | 137 + ...nkup-and-user_linkup_enabled-per-por.patch | 184 ++ ...am-ab-walk-through-port-list-non-rcu.patch | 27 + .../team/0020-team-add-missed-statics.patch | 66 + ...b-let-userspace-care-about-port-macs.patch | 41 + ...2-team-allow-to-enable-disable-ports.patch | 212 ++ ...t-option-for-enabling-disabling-port.patch | 54 + debian/patches/series-all | 28 + 28 files changed, 5573 insertions(+) create mode 100644 debian/patches/features/all/define-netdev_features_t.patch create mode 100644 debian/patches/features/all/filter-Allow-to-create-sk-unattached-filters.patch create mode 100644 debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch create mode 100644 debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch create mode 100644 debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch create mode 100644 debian/patches/features/all/team/0004-team-replicate-options-on-register.patch create mode 100644 debian/patches/features/all/team/0005-team-add-fix_features.patch create mode 100644 debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch create mode 100644 debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch create mode 100644 debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch create mode 100644 debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch create mode 100644 debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch create mode 100644 debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch create mode 100644 debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch create mode 100644 debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch create mode 100644 debian/patches/features/all/team/0014-team-add-binary-option-type.patch create mode 100644 debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch create mode 100644 debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch create mode 100644 debian/patches/features/all/team/0017-team-add-bool-option-type.patch create mode 100644 debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch create mode 100644 debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch create mode 100644 debian/patches/features/all/team/0020-team-add-missed-statics.patch create mode 100644 debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch create mode 100644 debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch create mode 100644 debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch diff --git a/debian/changelog b/debian/changelog index 72131cceb..003832033 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,6 +19,8 @@ linux (3.2.19-2) UNRELEASED; urgency=low * Convert patch system to quilt, except for the 'orig' patch series * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list modules as required even if they are built-in in some configurations + * filter: Allow to create sk-unattached filters + * net: Backport team driver from Linux 3.5-rc1 -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/config/config b/debian/config/config index 12c838caf..001ffd8d0 100644 --- a/debian/config/config +++ b/debian/config/config @@ -2075,6 +2075,14 @@ CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y +## +## file: drivers/net/team/Kconfig +## +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m + ## ## file: drivers/net/tokenring/Kconfig ## diff --git a/debian/patches/features/all/define-netdev_features_t.patch b/debian/patches/features/all/define-netdev_features_t.patch new file mode 100644 index 000000000..b11cc2ee6 --- /dev/null +++ b/debian/patches/features/all/define-netdev_features_t.patch @@ -0,0 +1,18 @@ +From: Ben Hutchings +Subject: Define netdev_features_t + +This was done in upstream commit +c8f44affb7244f2ac3e703cab13d55ede27621bb, but we just want the type +definition for use by backported drivers rather than changing +everything to use it. +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -950,6 +950,8 @@ + u32 features); + }; + ++typedef u32 netdev_features_t; ++ + /* + * The DEVICE structure. + * Actually, this whole structure is a big mistake. It mixes I/O diff --git a/debian/patches/features/all/filter-Allow-to-create-sk-unattached-filters.patch b/debian/patches/features/all/filter-Allow-to-create-sk-unattached-filters.patch new file mode 100644 index 000000000..f3fb9779b --- /dev/null +++ b/debian/patches/features/all/filter-Allow-to-create-sk-unattached-filters.patch @@ -0,0 +1,120 @@ +From: Jiri Pirko +Date: Sat, 31 Mar 2012 11:01:19 +0000 +Subject: filter: Allow to create sk-unattached filters + +commit 302d663740cfaf2c364df6bb61cd339014ed714c upstream. + +Today, BPF filters are bind to sockets. Since BPF machine becomes handy +for other purposes, this patch allows to create unattached filter. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + include/linux/filter.h | 3 +++ + net/core/filter.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 65 insertions(+), 4 deletions(-) + +diff --git a/include/linux/filter.h b/include/linux/filter.h +index 8eeb205..92dd993 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -153,6 +153,9 @@ static inline unsigned int sk_filter_len(const struct sk_filter *fp) + extern int sk_filter(struct sock *sk, struct sk_buff *skb); + extern unsigned int sk_run_filter(const struct sk_buff *skb, + const struct sock_filter *filter); ++extern int sk_unattached_filter_create(struct sk_filter **pfp, ++ struct sock_fprog *fprog); ++extern void sk_unattached_filter_destroy(struct sk_filter *fp); + extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); + extern int sk_detach_filter(struct sock *sk); + extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen); +diff --git a/net/core/filter.c b/net/core/filter.c +index 5dea452..cfbea88 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -587,6 +587,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu) + } + EXPORT_SYMBOL(sk_filter_release_rcu); + ++static int __sk_prepare_filter(struct sk_filter *fp) ++{ ++ int err; ++ ++ fp->bpf_func = sk_run_filter; ++ ++ err = sk_chk_filter(fp->insns, fp->len); ++ if (err) ++ return err; ++ ++ bpf_jit_compile(fp); ++ return 0; ++} ++ ++/** ++ * sk_unattached_filter_create - create an unattached filter ++ * @fprog: the filter program ++ * @sk: the socket to use ++ * ++ * Create a filter independent ofr any socket. We first run some ++ * sanity checks on it to make sure it does not explode on us later. ++ * If an error occurs or there is insufficient memory for the filter ++ * a negative errno code is returned. On success the return is zero. ++ */ ++int sk_unattached_filter_create(struct sk_filter **pfp, ++ struct sock_fprog *fprog) ++{ ++ struct sk_filter *fp; ++ unsigned int fsize = sizeof(struct sock_filter) * fprog->len; ++ int err; ++ ++ /* Make sure new filter is there and in the right amounts. */ ++ if (fprog->filter == NULL) ++ return -EINVAL; ++ ++ fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL); ++ if (!fp) ++ return -ENOMEM; ++ memcpy(fp->insns, fprog->filter, fsize); ++ ++ atomic_set(&fp->refcnt, 1); ++ fp->len = fprog->len; ++ ++ err = __sk_prepare_filter(fp); ++ if (err) ++ goto free_mem; ++ ++ *pfp = fp; ++ return 0; ++free_mem: ++ kfree(fp); ++ return err; ++} ++EXPORT_SYMBOL_GPL(sk_unattached_filter_create); ++ ++void sk_unattached_filter_destroy(struct sk_filter *fp) ++{ ++ sk_filter_release(fp); ++} ++EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy); ++ + /** + * sk_attach_filter - attach a socket filter + * @fprog: the filter program +@@ -617,16 +678,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) + + atomic_set(&fp->refcnt, 1); + fp->len = fprog->len; +- fp->bpf_func = sk_run_filter; + +- err = sk_chk_filter(fp->insns, fp->len); ++ err = __sk_prepare_filter(fp); + if (err) { + sk_filter_uncharge(sk, fp); + return err; + } + +- bpf_jit_compile(fp); +- + old_fp = rcu_dereference_protected(sk->sk_filter, + sock_owned_by_user(sk)); + rcu_assign_pointer(sk->sk_filter, fp); diff --git a/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch b/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch new file mode 100644 index 000000000..bfc901069 --- /dev/null +++ b/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch @@ -0,0 +1,2322 @@ +From: Jiri Pirko +Date: Fri, 11 Nov 2011 22:16:48 +0000 +Subject: [01/23] net: introduce ethernet teaming device + +commit 3d249d4ca7d0ed6629a135ea1ea21c72286c0d80 upstream. + +This patch introduces new network device called team. It supposes to be +very fast, simple, userspace-driven alternative to existing bonding +driver. + +Userspace library called libteam with couple of demo apps is available +here: +https://github.com/jpirko/libteam +Note it's still in its dipers atm. + +team<->libteam use generic netlink for communication. That and rtnl +suppose to be the only way to configure team device, no sysfs etc. + +Python binding of libteam was recently introduced. +Daemon providing arpmon/miimon active-backup functionality will be +introduced shortly. All what's necessary is already implemented in +kernel team driver. + +v7->v8: + - check ndo_ndo_vlan_rx_[add/kill]_vid functions before calling + them. + - use dev_kfree_skb_any() instead of dev_kfree_skb() + +v6->v7: + - transmit and receive functions are not checked in hot paths. + That also resolves memory leak on transmit when no port is + present + +v5->v6: + - changed couple of _rcu calls to non _rcu ones in non-readers + +v4->v5: + - team_change_mtu() uses team->lock while travesing though port + list + - mac address changes are moved completely to jurisdiction of + userspace daemon. This way the daemon can do FOM1, FOM2 and + possibly other weird things with mac addresses. + Only round-robin mode sets up all ports to bond's address then + enslaved. + - Extended Kconfig text + +v3->v4: + - remove redundant synchronize_rcu from __team_change_mode() + - revert "set and clear of mode_ops happens per pointer, not per + byte" + - extend comment of function __team_change_mode() + +v2->v3: + - team_change_mtu() uses rcu version of list traversal to unwind + - set and clear of mode_ops happens per pointer, not per byte + - port hashlist changed to be embedded into team structure + - error branch in team_port_enter() does cleanup now + - fixed rtln->rtnl + +v1->v2: + - modes are made as modules. Makes team more modular and + extendable. + - several commenters' nitpicks found on v1 were fixed + - several other bugs were fixed. + - note I ignored Eric's comment about roundrobin port selector + as Eric's way may be easily implemented as another mode (mode + "random") in future. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + Documentation/networking/team.txt | 2 + + MAINTAINERS | 7 + + drivers/net/Kconfig | 2 + + drivers/net/Makefile | 1 + + drivers/net/team/Kconfig | 43 + + drivers/net/team/Makefile | 7 + + drivers/net/team/team.c | 1583 +++++++++++++++++++++++++++++ + drivers/net/team/team_mode_activebackup.c | 137 +++ + drivers/net/team/team_mode_roundrobin.c | 107 ++ + include/linux/Kbuild | 1 + + include/linux/if.h | 1 + + include/linux/if_team.h | 242 +++++ + 12 files changed, 2133 insertions(+) + create mode 100644 Documentation/networking/team.txt + create mode 100644 drivers/net/team/Kconfig + create mode 100644 drivers/net/team/Makefile + create mode 100644 drivers/net/team/team.c + create mode 100644 drivers/net/team/team_mode_activebackup.c + create mode 100644 drivers/net/team/team_mode_roundrobin.c + create mode 100644 include/linux/if_team.h + +diff --git a/Documentation/networking/team.txt b/Documentation/networking/team.txt +new file mode 100644 +index 0000000..5a01368 +--- /dev/null ++++ b/Documentation/networking/team.txt +@@ -0,0 +1,2 @@ ++Team devices are driven from userspace via libteam library which is here: ++ https://github.com/jpirko/libteam +diff --git a/MAINTAINERS b/MAINTAINERS +index 4808256..8d94169 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -6484,6 +6484,13 @@ W: http://tcp-lp-mod.sourceforge.net/ + S: Maintained + F: net/ipv4/tcp_lp.c + ++TEAM DRIVER ++M: Jiri Pirko ++L: netdev@vger.kernel.org ++S: Supported ++F: drivers/net/team/ ++F: include/linux/if_team.h ++ + TEGRA SUPPORT + M: Colin Cross + M: Olof Johansson +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 583f66c..b3020be 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -125,6 +125,8 @@ config IFB + 'ifb1' etc. + Look at the iproute2 documentation directory for usage etc + ++source "drivers/net/team/Kconfig" ++ + config MACVLAN + tristate "MAC-VLAN support (EXPERIMENTAL)" + depends on EXPERIMENTAL +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index fa877cd..4e4ebfe 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_NET) += Space.o loopback.o + obj-$(CONFIG_NETCONSOLE) += netconsole.o + obj-$(CONFIG_PHYLIB) += phy/ + obj-$(CONFIG_RIONET) += rionet.o ++obj-$(CONFIG_NET_TEAM) += team/ + obj-$(CONFIG_TUN) += tun.o + obj-$(CONFIG_VETH) += veth.o + obj-$(CONFIG_VIRTIO_NET) += virtio_net.o +diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig +new file mode 100644 +index 0000000..248a144 +--- /dev/null ++++ b/drivers/net/team/Kconfig +@@ -0,0 +1,43 @@ ++menuconfig NET_TEAM ++ tristate "Ethernet team driver support (EXPERIMENTAL)" ++ depends on EXPERIMENTAL ++ ---help--- ++ This allows one to create virtual interfaces that teams together ++ multiple ethernet devices. ++ ++ Team devices can be added using the "ip" command from the ++ iproute2 package: ++ ++ "ip link add link [ address MAC ] [ NAME ] type team" ++ ++ To compile this driver as a module, choose M here: the module ++ will be called team. ++ ++if NET_TEAM ++ ++config NET_TEAM_MODE_ROUNDROBIN ++ tristate "Round-robin mode support" ++ depends on NET_TEAM ++ ---help--- ++ Basic mode where port used for transmitting packets is selected in ++ round-robin fashion using packet counter. ++ ++ All added ports are setup to have bond's mac address. ++ ++ To compile this team mode as a module, choose M here: the module ++ will be called team_mode_roundrobin. ++ ++config NET_TEAM_MODE_ACTIVEBACKUP ++ tristate "Active-backup mode support" ++ depends on NET_TEAM ++ ---help--- ++ Only one port is active at a time and the rest of ports are used ++ for backup. ++ ++ Mac addresses of ports are not modified. Userspace is responsible ++ to do so. ++ ++ To compile this team mode as a module, choose M here: the module ++ will be called team_mode_activebackup. ++ ++endif # NET_TEAM +diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile +new file mode 100644 +index 0000000..85f2028 +--- /dev/null ++++ b/drivers/net/team/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for the network team driver ++# ++ ++obj-$(CONFIG_NET_TEAM) += team.o ++obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o ++obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +new file mode 100644 +index 0000000..60672bb +--- /dev/null ++++ b/drivers/net/team/team.c +@@ -0,0 +1,1583 @@ ++/* ++ * net/drivers/team/team.c - Network team device driver ++ * Copyright (c) 2011 Jiri Pirko ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_NAME "team" ++ ++ ++/********** ++ * Helpers ++ **********/ ++ ++#define team_port_exists(dev) (dev->priv_flags & IFF_TEAM_PORT) ++ ++static struct team_port *team_port_get_rcu(const struct net_device *dev) ++{ ++ struct team_port *port = rcu_dereference(dev->rx_handler_data); ++ ++ return team_port_exists(dev) ? port : NULL; ++} ++ ++static struct team_port *team_port_get_rtnl(const struct net_device *dev) ++{ ++ struct team_port *port = rtnl_dereference(dev->rx_handler_data); ++ ++ return team_port_exists(dev) ? port : NULL; ++} ++ ++/* ++ * Since the ability to change mac address for open port device is tested in ++ * team_port_add, this function can be called without control of return value ++ */ ++static int __set_port_mac(struct net_device *port_dev, ++ const unsigned char *dev_addr) ++{ ++ struct sockaddr addr; ++ ++ memcpy(addr.sa_data, dev_addr, ETH_ALEN); ++ addr.sa_family = ARPHRD_ETHER; ++ return dev_set_mac_address(port_dev, &addr); ++} ++ ++int team_port_set_orig_mac(struct team_port *port) ++{ ++ return __set_port_mac(port->dev, port->orig.dev_addr); ++} ++ ++int team_port_set_team_mac(struct team_port *port) ++{ ++ return __set_port_mac(port->dev, port->team->dev->dev_addr); ++} ++EXPORT_SYMBOL(team_port_set_team_mac); ++ ++ ++/******************* ++ * Options handling ++ *******************/ ++ ++void team_options_register(struct team *team, struct team_option *option, ++ size_t option_count) ++{ ++ int i; ++ ++ for (i = 0; i < option_count; i++, option++) ++ list_add_tail(&option->list, &team->option_list); ++} ++EXPORT_SYMBOL(team_options_register); ++ ++static void __team_options_change_check(struct team *team, ++ struct team_option *changed_option); ++ ++static void __team_options_unregister(struct team *team, ++ struct team_option *option, ++ size_t option_count) ++{ ++ int i; ++ ++ for (i = 0; i < option_count; i++, option++) ++ list_del(&option->list); ++} ++ ++void team_options_unregister(struct team *team, struct team_option *option, ++ size_t option_count) ++{ ++ __team_options_unregister(team, option, option_count); ++ __team_options_change_check(team, NULL); ++} ++EXPORT_SYMBOL(team_options_unregister); ++ ++static int team_option_get(struct team *team, struct team_option *option, ++ void *arg) ++{ ++ return option->getter(team, arg); ++} ++ ++static int team_option_set(struct team *team, struct team_option *option, ++ void *arg) ++{ ++ int err; ++ ++ err = option->setter(team, arg); ++ if (err) ++ return err; ++ ++ __team_options_change_check(team, option); ++ return err; ++} ++ ++/**************** ++ * Mode handling ++ ****************/ ++ ++static LIST_HEAD(mode_list); ++static DEFINE_SPINLOCK(mode_list_lock); ++ ++static struct team_mode *__find_mode(const char *kind) ++{ ++ struct team_mode *mode; ++ ++ list_for_each_entry(mode, &mode_list, list) { ++ if (strcmp(mode->kind, kind) == 0) ++ return mode; ++ } ++ return NULL; ++} ++ ++static bool is_good_mode_name(const char *name) ++{ ++ while (*name != '\0') { ++ if (!isalpha(*name) && !isdigit(*name) && *name != '_') ++ return false; ++ name++; ++ } ++ return true; ++} ++ ++int team_mode_register(struct team_mode *mode) ++{ ++ int err = 0; ++ ++ if (!is_good_mode_name(mode->kind) || ++ mode->priv_size > TEAM_MODE_PRIV_SIZE) ++ return -EINVAL; ++ spin_lock(&mode_list_lock); ++ if (__find_mode(mode->kind)) { ++ err = -EEXIST; ++ goto unlock; ++ } ++ list_add_tail(&mode->list, &mode_list); ++unlock: ++ spin_unlock(&mode_list_lock); ++ return err; ++} ++EXPORT_SYMBOL(team_mode_register); ++ ++int team_mode_unregister(struct team_mode *mode) ++{ ++ spin_lock(&mode_list_lock); ++ list_del_init(&mode->list); ++ spin_unlock(&mode_list_lock); ++ return 0; ++} ++EXPORT_SYMBOL(team_mode_unregister); ++ ++static struct team_mode *team_mode_get(const char *kind) ++{ ++ struct team_mode *mode; ++ ++ spin_lock(&mode_list_lock); ++ mode = __find_mode(kind); ++ if (!mode) { ++ spin_unlock(&mode_list_lock); ++ request_module("team-mode-%s", kind); ++ spin_lock(&mode_list_lock); ++ mode = __find_mode(kind); ++ } ++ if (mode) ++ if (!try_module_get(mode->owner)) ++ mode = NULL; ++ ++ spin_unlock(&mode_list_lock); ++ return mode; ++} ++ ++static void team_mode_put(const struct team_mode *mode) ++{ ++ module_put(mode->owner); ++} ++ ++static bool team_dummy_transmit(struct team *team, struct sk_buff *skb) ++{ ++ dev_kfree_skb_any(skb); ++ return false; ++} ++ ++rx_handler_result_t team_dummy_receive(struct team *team, ++ struct team_port *port, ++ struct sk_buff *skb) ++{ ++ return RX_HANDLER_ANOTHER; ++} ++ ++static void team_adjust_ops(struct team *team) ++{ ++ /* ++ * To avoid checks in rx/tx skb paths, ensure here that non-null and ++ * correct ops are always set. ++ */ ++ ++ if (list_empty(&team->port_list) || ++ !team->mode || !team->mode->ops->transmit) ++ team->ops.transmit = team_dummy_transmit; ++ else ++ team->ops.transmit = team->mode->ops->transmit; ++ ++ if (list_empty(&team->port_list) || ++ !team->mode || !team->mode->ops->receive) ++ team->ops.receive = team_dummy_receive; ++ else ++ team->ops.receive = team->mode->ops->receive; ++} ++ ++/* ++ * We can benefit from the fact that it's ensured no port is present ++ * at the time of mode change. Therefore no packets are in fly so there's no ++ * need to set mode operations in any special way. ++ */ ++static int __team_change_mode(struct team *team, ++ const struct team_mode *new_mode) ++{ ++ /* Check if mode was previously set and do cleanup if so */ ++ if (team->mode) { ++ void (*exit_op)(struct team *team) = team->ops.exit; ++ ++ /* Clear ops area so no callback is called any longer */ ++ memset(&team->ops, 0, sizeof(struct team_mode_ops)); ++ team_adjust_ops(team); ++ ++ if (exit_op) ++ exit_op(team); ++ team_mode_put(team->mode); ++ team->mode = NULL; ++ /* zero private data area */ ++ memset(&team->mode_priv, 0, ++ sizeof(struct team) - offsetof(struct team, mode_priv)); ++ } ++ ++ if (!new_mode) ++ return 0; ++ ++ if (new_mode->ops->init) { ++ int err; ++ ++ err = new_mode->ops->init(team); ++ if (err) ++ return err; ++ } ++ ++ team->mode = new_mode; ++ memcpy(&team->ops, new_mode->ops, sizeof(struct team_mode_ops)); ++ team_adjust_ops(team); ++ ++ return 0; ++} ++ ++static int team_change_mode(struct team *team, const char *kind) ++{ ++ struct team_mode *new_mode; ++ struct net_device *dev = team->dev; ++ int err; ++ ++ if (!list_empty(&team->port_list)) { ++ netdev_err(dev, "No ports can be present during mode change\n"); ++ return -EBUSY; ++ } ++ ++ if (team->mode && strcmp(team->mode->kind, kind) == 0) { ++ netdev_err(dev, "Unable to change to the same mode the team is in\n"); ++ return -EINVAL; ++ } ++ ++ new_mode = team_mode_get(kind); ++ if (!new_mode) { ++ netdev_err(dev, "Mode \"%s\" not found\n", kind); ++ return -EINVAL; ++ } ++ ++ err = __team_change_mode(team, new_mode); ++ if (err) { ++ netdev_err(dev, "Failed to change to mode \"%s\"\n", kind); ++ team_mode_put(new_mode); ++ return err; ++ } ++ ++ netdev_info(dev, "Mode changed to \"%s\"\n", kind); ++ return 0; ++} ++ ++ ++/************************ ++ * Rx path frame handler ++ ************************/ ++ ++/* note: already called with rcu_read_lock */ ++static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ struct team_port *port; ++ struct team *team; ++ rx_handler_result_t res; ++ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (!skb) ++ return RX_HANDLER_CONSUMED; ++ ++ *pskb = skb; ++ ++ port = team_port_get_rcu(skb->dev); ++ team = port->team; ++ ++ res = team->ops.receive(team, port, skb); ++ if (res == RX_HANDLER_ANOTHER) { ++ struct team_pcpu_stats *pcpu_stats; ++ ++ pcpu_stats = this_cpu_ptr(team->pcpu_stats); ++ u64_stats_update_begin(&pcpu_stats->syncp); ++ pcpu_stats->rx_packets++; ++ pcpu_stats->rx_bytes += skb->len; ++ if (skb->pkt_type == PACKET_MULTICAST) ++ pcpu_stats->rx_multicast++; ++ u64_stats_update_end(&pcpu_stats->syncp); ++ ++ skb->dev = team->dev; ++ } else { ++ this_cpu_inc(team->pcpu_stats->rx_dropped); ++ } ++ ++ return res; ++} ++ ++ ++/**************** ++ * Port handling ++ ****************/ ++ ++static bool team_port_find(const struct team *team, ++ const struct team_port *port) ++{ ++ struct team_port *cur; ++ ++ list_for_each_entry(cur, &team->port_list, list) ++ if (cur == port) ++ return true; ++ return false; ++} ++ ++/* ++ * Add/delete port to the team port list. Write guarded by rtnl_lock. ++ * Takes care of correct port->index setup (might be racy). ++ */ ++static void team_port_list_add_port(struct team *team, ++ struct team_port *port) ++{ ++ port->index = team->port_count++; ++ hlist_add_head_rcu(&port->hlist, ++ team_port_index_hash(team, port->index)); ++ list_add_tail_rcu(&port->list, &team->port_list); ++} ++ ++static void __reconstruct_port_hlist(struct team *team, int rm_index) ++{ ++ int i; ++ struct team_port *port; ++ ++ for (i = rm_index + 1; i < team->port_count; i++) { ++ port = team_get_port_by_index(team, i); ++ hlist_del_rcu(&port->hlist); ++ port->index--; ++ hlist_add_head_rcu(&port->hlist, ++ team_port_index_hash(team, port->index)); ++ } ++} ++ ++static void team_port_list_del_port(struct team *team, ++ struct team_port *port) ++{ ++ int rm_index = port->index; ++ ++ hlist_del_rcu(&port->hlist); ++ list_del_rcu(&port->list); ++ __reconstruct_port_hlist(team, rm_index); ++ team->port_count--; ++} ++ ++#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ ++ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ ++ NETIF_F_HIGHDMA | NETIF_F_LRO) ++ ++static void __team_compute_features(struct team *team) ++{ ++ struct team_port *port; ++ u32 vlan_features = TEAM_VLAN_FEATURES; ++ unsigned short max_hard_header_len = ETH_HLEN; ++ ++ list_for_each_entry(port, &team->port_list, list) { ++ vlan_features = netdev_increment_features(vlan_features, ++ port->dev->vlan_features, ++ TEAM_VLAN_FEATURES); ++ ++ if (port->dev->hard_header_len > max_hard_header_len) ++ max_hard_header_len = port->dev->hard_header_len; ++ } ++ ++ team->dev->vlan_features = vlan_features; ++ team->dev->hard_header_len = max_hard_header_len; ++ ++ netdev_change_features(team->dev); ++} ++ ++static void team_compute_features(struct team *team) ++{ ++ spin_lock(&team->lock); ++ __team_compute_features(team); ++ spin_unlock(&team->lock); ++} ++ ++static int team_port_enter(struct team *team, struct team_port *port) ++{ ++ int err = 0; ++ ++ dev_hold(team->dev); ++ port->dev->priv_flags |= IFF_TEAM_PORT; ++ if (team->ops.port_enter) { ++ err = team->ops.port_enter(team, port); ++ if (err) { ++ netdev_err(team->dev, "Device %s failed to enter team mode\n", ++ port->dev->name); ++ goto err_port_enter; ++ } ++ } ++ ++ return 0; ++ ++err_port_enter: ++ port->dev->priv_flags &= ~IFF_TEAM_PORT; ++ dev_put(team->dev); ++ ++ return err; ++} ++ ++static void team_port_leave(struct team *team, struct team_port *port) ++{ ++ if (team->ops.port_leave) ++ team->ops.port_leave(team, port); ++ port->dev->priv_flags &= ~IFF_TEAM_PORT; ++ dev_put(team->dev); ++} ++ ++static void __team_port_change_check(struct team_port *port, bool linkup); ++ ++static int team_port_add(struct team *team, struct net_device *port_dev) ++{ ++ struct net_device *dev = team->dev; ++ struct team_port *port; ++ char *portname = port_dev->name; ++ int err; ++ ++ if (port_dev->flags & IFF_LOOPBACK || ++ port_dev->type != ARPHRD_ETHER) { ++ netdev_err(dev, "Device %s is of an unsupported type\n", ++ portname); ++ return -EINVAL; ++ } ++ ++ if (team_port_exists(port_dev)) { ++ netdev_err(dev, "Device %s is already a port " ++ "of a team device\n", portname); ++ return -EBUSY; ++ } ++ ++ if (port_dev->flags & IFF_UP) { ++ netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", ++ portname); ++ return -EBUSY; ++ } ++ ++ port = kzalloc(sizeof(struct team_port), GFP_KERNEL); ++ if (!port) ++ return -ENOMEM; ++ ++ port->dev = port_dev; ++ port->team = team; ++ ++ port->orig.mtu = port_dev->mtu; ++ err = dev_set_mtu(port_dev, dev->mtu); ++ if (err) { ++ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); ++ goto err_set_mtu; ++ } ++ ++ memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); ++ ++ err = team_port_enter(team, port); ++ if (err) { ++ netdev_err(dev, "Device %s failed to enter team mode\n", ++ portname); ++ goto err_port_enter; ++ } ++ ++ err = dev_open(port_dev); ++ if (err) { ++ netdev_dbg(dev, "Device %s opening failed\n", ++ portname); ++ goto err_dev_open; ++ } ++ ++ err = netdev_set_master(port_dev, dev); ++ if (err) { ++ netdev_err(dev, "Device %s failed to set master\n", portname); ++ goto err_set_master; ++ } ++ ++ err = netdev_rx_handler_register(port_dev, team_handle_frame, ++ port); ++ if (err) { ++ netdev_err(dev, "Device %s failed to register rx_handler\n", ++ portname); ++ goto err_handler_register; ++ } ++ ++ team_port_list_add_port(team, port); ++ team_adjust_ops(team); ++ __team_compute_features(team); ++ __team_port_change_check(port, !!netif_carrier_ok(port_dev)); ++ ++ netdev_info(dev, "Port device %s added\n", portname); ++ ++ return 0; ++ ++err_handler_register: ++ netdev_set_master(port_dev, NULL); ++ ++err_set_master: ++ dev_close(port_dev); ++ ++err_dev_open: ++ team_port_leave(team, port); ++ team_port_set_orig_mac(port); ++ ++err_port_enter: ++ dev_set_mtu(port_dev, port->orig.mtu); ++ ++err_set_mtu: ++ kfree(port); ++ ++ return err; ++} ++ ++static int team_port_del(struct team *team, struct net_device *port_dev) ++{ ++ struct net_device *dev = team->dev; ++ struct team_port *port; ++ char *portname = port_dev->name; ++ ++ port = team_port_get_rtnl(port_dev); ++ if (!port || !team_port_find(team, port)) { ++ netdev_err(dev, "Device %s does not act as a port of this team\n", ++ portname); ++ return -ENOENT; ++ } ++ ++ __team_port_change_check(port, false); ++ team_port_list_del_port(team, port); ++ team_adjust_ops(team); ++ netdev_rx_handler_unregister(port_dev); ++ netdev_set_master(port_dev, NULL); ++ dev_close(port_dev); ++ team_port_leave(team, port); ++ team_port_set_orig_mac(port); ++ dev_set_mtu(port_dev, port->orig.mtu); ++ synchronize_rcu(); ++ kfree(port); ++ netdev_info(dev, "Port device %s removed\n", portname); ++ __team_compute_features(team); ++ ++ return 0; ++} ++ ++ ++/***************** ++ * Net device ops ++ *****************/ ++ ++static const char team_no_mode_kind[] = "*NOMODE*"; ++ ++static int team_mode_option_get(struct team *team, void *arg) ++{ ++ const char **str = arg; ++ ++ *str = team->mode ? team->mode->kind : team_no_mode_kind; ++ return 0; ++} ++ ++static int team_mode_option_set(struct team *team, void *arg) ++{ ++ const char **str = arg; ++ ++ return team_change_mode(team, *str); ++} ++ ++static struct team_option team_options[] = { ++ { ++ .name = "mode", ++ .type = TEAM_OPTION_TYPE_STRING, ++ .getter = team_mode_option_get, ++ .setter = team_mode_option_set, ++ }, ++}; ++ ++static int team_init(struct net_device *dev) ++{ ++ struct team *team = netdev_priv(dev); ++ int i; ++ ++ team->dev = dev; ++ spin_lock_init(&team->lock); ++ ++ team->pcpu_stats = alloc_percpu(struct team_pcpu_stats); ++ if (!team->pcpu_stats) ++ return -ENOMEM; ++ ++ for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) ++ INIT_HLIST_HEAD(&team->port_hlist[i]); ++ INIT_LIST_HEAD(&team->port_list); ++ ++ team_adjust_ops(team); ++ ++ INIT_LIST_HEAD(&team->option_list); ++ team_options_register(team, team_options, ARRAY_SIZE(team_options)); ++ netif_carrier_off(dev); ++ ++ return 0; ++} ++ ++static void team_uninit(struct net_device *dev) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ struct team_port *tmp; ++ ++ spin_lock(&team->lock); ++ list_for_each_entry_safe(port, tmp, &team->port_list, list) ++ team_port_del(team, port->dev); ++ ++ __team_change_mode(team, NULL); /* cleanup */ ++ __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); ++ spin_unlock(&team->lock); ++} ++ ++static void team_destructor(struct net_device *dev) ++{ ++ struct team *team = netdev_priv(dev); ++ ++ free_percpu(team->pcpu_stats); ++ free_netdev(dev); ++} ++ ++static int team_open(struct net_device *dev) ++{ ++ netif_carrier_on(dev); ++ return 0; ++} ++ ++static int team_close(struct net_device *dev) ++{ ++ netif_carrier_off(dev); ++ return 0; ++} ++ ++/* ++ * note: already called with rcu_read_lock ++ */ ++static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct team *team = netdev_priv(dev); ++ bool tx_success = false; ++ unsigned int len = skb->len; ++ ++ tx_success = team->ops.transmit(team, skb); ++ if (tx_success) { ++ struct team_pcpu_stats *pcpu_stats; ++ ++ pcpu_stats = this_cpu_ptr(team->pcpu_stats); ++ u64_stats_update_begin(&pcpu_stats->syncp); ++ pcpu_stats->tx_packets++; ++ pcpu_stats->tx_bytes += len; ++ u64_stats_update_end(&pcpu_stats->syncp); ++ } else { ++ this_cpu_inc(team->pcpu_stats->tx_dropped); ++ } ++ ++ return NETDEV_TX_OK; ++} ++ ++static void team_change_rx_flags(struct net_device *dev, int change) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ int inc; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ if (change & IFF_PROMISC) { ++ inc = dev->flags & IFF_PROMISC ? 1 : -1; ++ dev_set_promiscuity(port->dev, inc); ++ } ++ if (change & IFF_ALLMULTI) { ++ inc = dev->flags & IFF_ALLMULTI ? 1 : -1; ++ dev_set_allmulti(port->dev, inc); ++ } ++ } ++ rcu_read_unlock(); ++} ++ ++static void team_set_rx_mode(struct net_device *dev) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ dev_uc_sync(port->dev, dev); ++ dev_mc_sync(port->dev, dev); ++ } ++ rcu_read_unlock(); ++} ++ ++static int team_set_mac_address(struct net_device *dev, void *p) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ struct sockaddr *addr = p; ++ ++ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) ++ if (team->ops.port_change_mac) ++ team->ops.port_change_mac(team, port); ++ rcu_read_unlock(); ++ return 0; ++} ++ ++static int team_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ int err; ++ ++ /* ++ * Alhough this is reader, it's guarded by team lock. It's not possible ++ * to traverse list in reverse under rcu_read_lock ++ */ ++ spin_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) { ++ err = dev_set_mtu(port->dev, new_mtu); ++ if (err) { ++ netdev_err(dev, "Device %s failed to change mtu", ++ port->dev->name); ++ goto unwind; ++ } ++ } ++ spin_unlock(&team->lock); ++ ++ dev->mtu = new_mtu; ++ ++ return 0; ++ ++unwind: ++ list_for_each_entry_continue_reverse(port, &team->port_list, list) ++ dev_set_mtu(port->dev, dev->mtu); ++ spin_unlock(&team->lock); ++ ++ return err; ++} ++ ++static struct rtnl_link_stats64 * ++team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_pcpu_stats *p; ++ u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes; ++ u32 rx_dropped = 0, tx_dropped = 0; ++ unsigned int start; ++ int i; ++ ++ for_each_possible_cpu(i) { ++ p = per_cpu_ptr(team->pcpu_stats, i); ++ do { ++ start = u64_stats_fetch_begin_bh(&p->syncp); ++ rx_packets = p->rx_packets; ++ rx_bytes = p->rx_bytes; ++ rx_multicast = p->rx_multicast; ++ tx_packets = p->tx_packets; ++ tx_bytes = p->tx_bytes; ++ } while (u64_stats_fetch_retry_bh(&p->syncp, start)); ++ ++ stats->rx_packets += rx_packets; ++ stats->rx_bytes += rx_bytes; ++ stats->multicast += rx_multicast; ++ stats->tx_packets += tx_packets; ++ stats->tx_bytes += tx_bytes; ++ /* ++ * rx_dropped & tx_dropped are u32, updated ++ * without syncp protection. ++ */ ++ rx_dropped += p->rx_dropped; ++ tx_dropped += p->tx_dropped; ++ } ++ stats->rx_dropped = rx_dropped; ++ stats->tx_dropped = tx_dropped; ++ return stats; ++} ++ ++static void team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ const struct net_device_ops *ops = port->dev->netdev_ops; ++ ++ if (ops->ndo_vlan_rx_add_vid) ++ ops->ndo_vlan_rx_add_vid(port->dev, vid); ++ } ++ rcu_read_unlock(); ++} ++ ++static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) ++{ ++ struct team *team = netdev_priv(dev); ++ struct team_port *port; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ const struct net_device_ops *ops = port->dev->netdev_ops; ++ ++ if (ops->ndo_vlan_rx_kill_vid) ++ ops->ndo_vlan_rx_kill_vid(port->dev, vid); ++ } ++ rcu_read_unlock(); ++} ++ ++static int team_add_slave(struct net_device *dev, struct net_device *port_dev) ++{ ++ struct team *team = netdev_priv(dev); ++ int err; ++ ++ spin_lock(&team->lock); ++ err = team_port_add(team, port_dev); ++ spin_unlock(&team->lock); ++ return err; ++} ++ ++static int team_del_slave(struct net_device *dev, struct net_device *port_dev) ++{ ++ struct team *team = netdev_priv(dev); ++ int err; ++ ++ spin_lock(&team->lock); ++ err = team_port_del(team, port_dev); ++ spin_unlock(&team->lock); ++ return err; ++} ++ ++static const struct net_device_ops team_netdev_ops = { ++ .ndo_init = team_init, ++ .ndo_uninit = team_uninit, ++ .ndo_open = team_open, ++ .ndo_stop = team_close, ++ .ndo_start_xmit = team_xmit, ++ .ndo_change_rx_flags = team_change_rx_flags, ++ .ndo_set_rx_mode = team_set_rx_mode, ++ .ndo_set_mac_address = team_set_mac_address, ++ .ndo_change_mtu = team_change_mtu, ++ .ndo_get_stats64 = team_get_stats64, ++ .ndo_vlan_rx_add_vid = team_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = team_vlan_rx_kill_vid, ++ .ndo_add_slave = team_add_slave, ++ .ndo_del_slave = team_del_slave, ++}; ++ ++ ++/*********************** ++ * rt netlink interface ++ ***********************/ ++ ++static void team_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ ++ dev->netdev_ops = &team_netdev_ops; ++ dev->destructor = team_destructor; ++ dev->tx_queue_len = 0; ++ dev->flags |= IFF_MULTICAST; ++ dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); ++ ++ /* ++ * Indicate we support unicast address filtering. That way core won't ++ * bring us to promisc mode in case a unicast addr is added. ++ * Let this up to underlay drivers. ++ */ ++ dev->priv_flags |= IFF_UNICAST_FLT; ++ ++ dev->features |= NETIF_F_LLTX; ++ dev->features |= NETIF_F_GRO; ++ dev->hw_features = NETIF_F_HW_VLAN_TX | ++ NETIF_F_HW_VLAN_RX | ++ NETIF_F_HW_VLAN_FILTER; ++ ++ dev->features |= dev->hw_features; ++} ++ ++static int team_newlink(struct net *src_net, struct net_device *dev, ++ struct nlattr *tb[], struct nlattr *data[]) ++{ ++ int err; ++ ++ if (tb[IFLA_ADDRESS] == NULL) ++ random_ether_addr(dev->dev_addr); ++ ++ err = register_netdevice(dev); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static int team_validate(struct nlattr *tb[], struct nlattr *data[]) ++{ ++ if (tb[IFLA_ADDRESS]) { ++ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) ++ return -EINVAL; ++ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) ++ return -EADDRNOTAVAIL; ++ } ++ return 0; ++} ++ ++static struct rtnl_link_ops team_link_ops __read_mostly = { ++ .kind = DRV_NAME, ++ .priv_size = sizeof(struct team), ++ .setup = team_setup, ++ .newlink = team_newlink, ++ .validate = team_validate, ++}; ++ ++ ++/*********************************** ++ * Generic netlink custom interface ++ ***********************************/ ++ ++static struct genl_family team_nl_family = { ++ .id = GENL_ID_GENERATE, ++ .name = TEAM_GENL_NAME, ++ .version = TEAM_GENL_VERSION, ++ .maxattr = TEAM_ATTR_MAX, ++ .netnsok = true, ++}; ++ ++static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = { ++ [TEAM_ATTR_UNSPEC] = { .type = NLA_UNSPEC, }, ++ [TEAM_ATTR_TEAM_IFINDEX] = { .type = NLA_U32 }, ++ [TEAM_ATTR_LIST_OPTION] = { .type = NLA_NESTED }, ++ [TEAM_ATTR_LIST_PORT] = { .type = NLA_NESTED }, ++}; ++ ++static const struct nla_policy ++team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { ++ [TEAM_ATTR_OPTION_UNSPEC] = { .type = NLA_UNSPEC, }, ++ [TEAM_ATTR_OPTION_NAME] = { ++ .type = NLA_STRING, ++ .len = TEAM_STRING_MAX_LEN, ++ }, ++ [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, ++ [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, ++ [TEAM_ATTR_OPTION_DATA] = { ++ .type = NLA_BINARY, ++ .len = TEAM_STRING_MAX_LEN, ++ }, ++}; ++ ++static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct sk_buff *msg; ++ void *hdr; ++ int err; ++ ++ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!msg) ++ return -ENOMEM; ++ ++ hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, ++ &team_nl_family, 0, TEAM_CMD_NOOP); ++ if (IS_ERR(hdr)) { ++ err = PTR_ERR(hdr); ++ goto err_msg_put; ++ } ++ ++ genlmsg_end(msg, hdr); ++ ++ return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); ++ ++err_msg_put: ++ nlmsg_free(msg); ++ ++ return err; ++} ++ ++/* ++ * Netlink cmd functions should be locked by following two functions. ++ * To ensure team_uninit would not be called in between, hold rcu_read_lock ++ * all the time. ++ */ ++static struct team *team_nl_team_get(struct genl_info *info) ++{ ++ struct net *net = genl_info_net(info); ++ int ifindex; ++ struct net_device *dev; ++ struct team *team; ++ ++ if (!info->attrs[TEAM_ATTR_TEAM_IFINDEX]) ++ return NULL; ++ ++ ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]); ++ rcu_read_lock(); ++ dev = dev_get_by_index_rcu(net, ifindex); ++ if (!dev || dev->netdev_ops != &team_netdev_ops) { ++ rcu_read_unlock(); ++ return NULL; ++ } ++ ++ team = netdev_priv(dev); ++ spin_lock(&team->lock); ++ return team; ++} ++ ++static void team_nl_team_put(struct team *team) ++{ ++ spin_unlock(&team->lock); ++ rcu_read_unlock(); ++} ++ ++static int team_nl_send_generic(struct genl_info *info, struct team *team, ++ int (*fill_func)(struct sk_buff *skb, ++ struct genl_info *info, ++ int flags, struct team *team)) ++{ ++ struct sk_buff *skb; ++ int err; ++ ++ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!skb) ++ return -ENOMEM; ++ ++ err = fill_func(skb, info, NLM_F_ACK, team); ++ if (err < 0) ++ goto err_fill; ++ ++ err = genlmsg_unicast(genl_info_net(info), skb, info->snd_pid); ++ return err; ++ ++err_fill: ++ nlmsg_free(skb); ++ return err; ++} ++ ++static int team_nl_fill_options_get_changed(struct sk_buff *skb, ++ u32 pid, u32 seq, int flags, ++ struct team *team, ++ struct team_option *changed_option) ++{ ++ struct nlattr *option_list; ++ void *hdr; ++ struct team_option *option; ++ ++ hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, ++ TEAM_CMD_OPTIONS_GET); ++ if (IS_ERR(hdr)) ++ return PTR_ERR(hdr); ++ ++ NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); ++ option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION); ++ if (!option_list) ++ return -EMSGSIZE; ++ ++ list_for_each_entry(option, &team->option_list, list) { ++ struct nlattr *option_item; ++ long arg; ++ ++ option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); ++ if (!option_item) ++ goto nla_put_failure; ++ NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); ++ if (option == changed_option) ++ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); ++ switch (option->type) { ++ case TEAM_OPTION_TYPE_U32: ++ NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); ++ team_option_get(team, option, &arg); ++ NLA_PUT_U32(skb, TEAM_ATTR_OPTION_DATA, arg); ++ break; ++ case TEAM_OPTION_TYPE_STRING: ++ NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING); ++ team_option_get(team, option, &arg); ++ NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_DATA, ++ (char *) arg); ++ break; ++ default: ++ BUG(); ++ } ++ nla_nest_end(skb, option_item); ++ } ++ ++ nla_nest_end(skb, option_list); ++ return genlmsg_end(skb, hdr); ++ ++nla_put_failure: ++ genlmsg_cancel(skb, hdr); ++ return -EMSGSIZE; ++} ++ ++static int team_nl_fill_options_get(struct sk_buff *skb, ++ struct genl_info *info, int flags, ++ struct team *team) ++{ ++ return team_nl_fill_options_get_changed(skb, info->snd_pid, ++ info->snd_seq, NLM_F_ACK, ++ team, NULL); ++} ++ ++static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct team *team; ++ int err; ++ ++ team = team_nl_team_get(info); ++ if (!team) ++ return -EINVAL; ++ ++ err = team_nl_send_generic(info, team, team_nl_fill_options_get); ++ ++ team_nl_team_put(team); ++ ++ return err; ++} ++ ++static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct team *team; ++ int err = 0; ++ int i; ++ struct nlattr *nl_option; ++ ++ team = team_nl_team_get(info); ++ if (!team) ++ return -EINVAL; ++ ++ err = -EINVAL; ++ if (!info->attrs[TEAM_ATTR_LIST_OPTION]) { ++ err = -EINVAL; ++ goto team_put; ++ } ++ ++ nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { ++ struct nlattr *mode_attrs[TEAM_ATTR_OPTION_MAX + 1]; ++ enum team_option_type opt_type; ++ struct team_option *option; ++ char *opt_name; ++ bool opt_found = false; ++ ++ if (nla_type(nl_option) != TEAM_ATTR_ITEM_OPTION) { ++ err = -EINVAL; ++ goto team_put; ++ } ++ err = nla_parse_nested(mode_attrs, TEAM_ATTR_OPTION_MAX, ++ nl_option, team_nl_option_policy); ++ if (err) ++ goto team_put; ++ if (!mode_attrs[TEAM_ATTR_OPTION_NAME] || ++ !mode_attrs[TEAM_ATTR_OPTION_TYPE] || ++ !mode_attrs[TEAM_ATTR_OPTION_DATA]) { ++ err = -EINVAL; ++ goto team_put; ++ } ++ switch (nla_get_u8(mode_attrs[TEAM_ATTR_OPTION_TYPE])) { ++ case NLA_U32: ++ opt_type = TEAM_OPTION_TYPE_U32; ++ break; ++ case NLA_STRING: ++ opt_type = TEAM_OPTION_TYPE_STRING; ++ break; ++ default: ++ goto team_put; ++ } ++ ++ opt_name = nla_data(mode_attrs[TEAM_ATTR_OPTION_NAME]); ++ list_for_each_entry(option, &team->option_list, list) { ++ long arg; ++ struct nlattr *opt_data_attr; ++ ++ if (option->type != opt_type || ++ strcmp(option->name, opt_name)) ++ continue; ++ opt_found = true; ++ opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; ++ switch (opt_type) { ++ case TEAM_OPTION_TYPE_U32: ++ arg = nla_get_u32(opt_data_attr); ++ break; ++ case TEAM_OPTION_TYPE_STRING: ++ arg = (long) nla_data(opt_data_attr); ++ break; ++ default: ++ BUG(); ++ } ++ err = team_option_set(team, option, &arg); ++ if (err) ++ goto team_put; ++ } ++ if (!opt_found) { ++ err = -ENOENT; ++ goto team_put; ++ } ++ } ++ ++team_put: ++ team_nl_team_put(team); ++ ++ return err; ++} ++ ++static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, ++ u32 pid, u32 seq, int flags, ++ struct team *team, ++ struct team_port *changed_port) ++{ ++ struct nlattr *port_list; ++ void *hdr; ++ struct team_port *port; ++ ++ hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, ++ TEAM_CMD_PORT_LIST_GET); ++ if (IS_ERR(hdr)) ++ return PTR_ERR(hdr); ++ ++ NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); ++ port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT); ++ if (!port_list) ++ return -EMSGSIZE; ++ ++ list_for_each_entry(port, &team->port_list, list) { ++ struct nlattr *port_item; ++ ++ port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); ++ if (!port_item) ++ goto nla_put_failure; ++ NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); ++ if (port == changed_port) ++ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); ++ if (port->linkup) ++ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); ++ NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); ++ NLA_PUT_U8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex); ++ nla_nest_end(skb, port_item); ++ } ++ ++ nla_nest_end(skb, port_list); ++ return genlmsg_end(skb, hdr); ++ ++nla_put_failure: ++ genlmsg_cancel(skb, hdr); ++ return -EMSGSIZE; ++} ++ ++static int team_nl_fill_port_list_get(struct sk_buff *skb, ++ struct genl_info *info, int flags, ++ struct team *team) ++{ ++ return team_nl_fill_port_list_get_changed(skb, info->snd_pid, ++ info->snd_seq, NLM_F_ACK, ++ team, NULL); ++} ++ ++static int team_nl_cmd_port_list_get(struct sk_buff *skb, ++ struct genl_info *info) ++{ ++ struct team *team; ++ int err; ++ ++ team = team_nl_team_get(info); ++ if (!team) ++ return -EINVAL; ++ ++ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get); ++ ++ team_nl_team_put(team); ++ ++ return err; ++} ++ ++static struct genl_ops team_nl_ops[] = { ++ { ++ .cmd = TEAM_CMD_NOOP, ++ .doit = team_nl_cmd_noop, ++ .policy = team_nl_policy, ++ }, ++ { ++ .cmd = TEAM_CMD_OPTIONS_SET, ++ .doit = team_nl_cmd_options_set, ++ .policy = team_nl_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = TEAM_CMD_OPTIONS_GET, ++ .doit = team_nl_cmd_options_get, ++ .policy = team_nl_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = TEAM_CMD_PORT_LIST_GET, ++ .doit = team_nl_cmd_port_list_get, ++ .policy = team_nl_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++}; ++ ++static struct genl_multicast_group team_change_event_mcgrp = { ++ .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, ++}; ++ ++static int team_nl_send_event_options_get(struct team *team, ++ struct team_option *changed_option) ++{ ++ struct sk_buff *skb; ++ int err; ++ struct net *net = dev_net(team->dev); ++ ++ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!skb) ++ return -ENOMEM; ++ ++ err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team, ++ changed_option); ++ if (err < 0) ++ goto err_fill; ++ ++ err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, ++ GFP_KERNEL); ++ return err; ++ ++err_fill: ++ nlmsg_free(skb); ++ return err; ++} ++ ++static int team_nl_send_event_port_list_get(struct team_port *port) ++{ ++ struct sk_buff *skb; ++ int err; ++ struct net *net = dev_net(port->team->dev); ++ ++ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!skb) ++ return -ENOMEM; ++ ++ err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0, ++ port->team, port); ++ if (err < 0) ++ goto err_fill; ++ ++ err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, ++ GFP_KERNEL); ++ return err; ++ ++err_fill: ++ nlmsg_free(skb); ++ return err; ++} ++ ++static int team_nl_init(void) ++{ ++ int err; ++ ++ err = genl_register_family_with_ops(&team_nl_family, team_nl_ops, ++ ARRAY_SIZE(team_nl_ops)); ++ if (err) ++ return err; ++ ++ err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp); ++ if (err) ++ goto err_change_event_grp_reg; ++ ++ return 0; ++ ++err_change_event_grp_reg: ++ genl_unregister_family(&team_nl_family); ++ ++ return err; ++} ++ ++static void team_nl_fini(void) ++{ ++ genl_unregister_family(&team_nl_family); ++} ++ ++ ++/****************** ++ * Change checkers ++ ******************/ ++ ++static void __team_options_change_check(struct team *team, ++ struct team_option *changed_option) ++{ ++ int err; ++ ++ err = team_nl_send_event_options_get(team, changed_option); ++ if (err) ++ netdev_warn(team->dev, "Failed to send options change via netlink\n"); ++} ++ ++/* rtnl lock is held */ ++static void __team_port_change_check(struct team_port *port, bool linkup) ++{ ++ int err; ++ ++ if (port->linkup == linkup) ++ return; ++ ++ port->linkup = linkup; ++ if (linkup) { ++ struct ethtool_cmd ecmd; ++ ++ err = __ethtool_get_settings(port->dev, &ecmd); ++ if (!err) { ++ port->speed = ethtool_cmd_speed(&ecmd); ++ port->duplex = ecmd.duplex; ++ goto send_event; ++ } ++ } ++ port->speed = 0; ++ port->duplex = 0; ++ ++send_event: ++ err = team_nl_send_event_port_list_get(port); ++ if (err) ++ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", ++ port->dev->name); ++ ++} ++ ++static void team_port_change_check(struct team_port *port, bool linkup) ++{ ++ struct team *team = port->team; ++ ++ spin_lock(&team->lock); ++ __team_port_change_check(port, linkup); ++ spin_unlock(&team->lock); ++} ++ ++/************************************ ++ * Net device notifier event handler ++ ************************************/ ++ ++static int team_device_event(struct notifier_block *unused, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = (struct net_device *) ptr; ++ struct team_port *port; ++ ++ port = team_port_get_rtnl(dev); ++ if (!port) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case NETDEV_UP: ++ if (netif_carrier_ok(dev)) ++ team_port_change_check(port, true); ++ case NETDEV_DOWN: ++ team_port_change_check(port, false); ++ case NETDEV_CHANGE: ++ if (netif_running(port->dev)) ++ team_port_change_check(port, ++ !!netif_carrier_ok(port->dev)); ++ break; ++ case NETDEV_UNREGISTER: ++ team_del_slave(port->team->dev, dev); ++ break; ++ case NETDEV_FEAT_CHANGE: ++ team_compute_features(port->team); ++ break; ++ case NETDEV_CHANGEMTU: ++ /* Forbid to change mtu of underlaying device */ ++ return NOTIFY_BAD; ++ case NETDEV_PRE_TYPE_CHANGE: ++ /* Forbid to change type of underlaying device */ ++ return NOTIFY_BAD; ++ } ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block team_notifier_block __read_mostly = { ++ .notifier_call = team_device_event, ++}; ++ ++ ++/*********************** ++ * Module init and exit ++ ***********************/ ++ ++static int __init team_module_init(void) ++{ ++ int err; ++ ++ register_netdevice_notifier(&team_notifier_block); ++ ++ err = rtnl_link_register(&team_link_ops); ++ if (err) ++ goto err_rtnl_reg; ++ ++ err = team_nl_init(); ++ if (err) ++ goto err_nl_init; ++ ++ return 0; ++ ++err_nl_init: ++ rtnl_link_unregister(&team_link_ops); ++ ++err_rtnl_reg: ++ unregister_netdevice_notifier(&team_notifier_block); ++ ++ return err; ++} ++ ++static void __exit team_module_exit(void) ++{ ++ team_nl_fini(); ++ rtnl_link_unregister(&team_link_ops); ++ unregister_netdevice_notifier(&team_notifier_block); ++} ++ ++module_init(team_module_init); ++module_exit(team_module_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Jiri Pirko "); ++MODULE_DESCRIPTION("Ethernet team device driver"); ++MODULE_ALIAS_RTNL_LINK(DRV_NAME); +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +new file mode 100644 +index 0000000..6fe920c +--- /dev/null ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -0,0 +1,137 @@ ++/* ++ * net/drivers/team/team_mode_activebackup.c - Active-backup mode for team ++ * Copyright (c) 2011 Jiri Pirko ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ab_priv { ++ struct team_port __rcu *active_port; ++}; ++ ++static struct ab_priv *ab_priv(struct team *team) ++{ ++ return (struct ab_priv *) &team->mode_priv; ++} ++ ++static rx_handler_result_t ab_receive(struct team *team, struct team_port *port, ++ struct sk_buff *skb) { ++ struct team_port *active_port; ++ ++ active_port = rcu_dereference(ab_priv(team)->active_port); ++ if (active_port != port) ++ return RX_HANDLER_EXACT; ++ return RX_HANDLER_ANOTHER; ++} ++ ++static bool ab_transmit(struct team *team, struct sk_buff *skb) ++{ ++ struct team_port *active_port; ++ ++ active_port = rcu_dereference(ab_priv(team)->active_port); ++ if (unlikely(!active_port)) ++ goto drop; ++ skb->dev = active_port->dev; ++ if (dev_queue_xmit(skb)) ++ return false; ++ return true; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ return false; ++} ++ ++static void ab_port_leave(struct team *team, struct team_port *port) ++{ ++ if (ab_priv(team)->active_port == port) ++ rcu_assign_pointer(ab_priv(team)->active_port, NULL); ++} ++ ++static int ab_active_port_get(struct team *team, void *arg) ++{ ++ u32 *ifindex = arg; ++ ++ *ifindex = 0; ++ if (ab_priv(team)->active_port) ++ *ifindex = ab_priv(team)->active_port->dev->ifindex; ++ return 0; ++} ++ ++static int ab_active_port_set(struct team *team, void *arg) ++{ ++ u32 *ifindex = arg; ++ struct team_port *port; ++ ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ if (port->dev->ifindex == *ifindex) { ++ rcu_assign_pointer(ab_priv(team)->active_port, port); ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ ++static struct team_option ab_options[] = { ++ { ++ .name = "activeport", ++ .type = TEAM_OPTION_TYPE_U32, ++ .getter = ab_active_port_get, ++ .setter = ab_active_port_set, ++ }, ++}; ++ ++int ab_init(struct team *team) ++{ ++ team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); ++ return 0; ++} ++ ++void ab_exit(struct team *team) ++{ ++ team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options)); ++} ++ ++static const struct team_mode_ops ab_mode_ops = { ++ .init = ab_init, ++ .exit = ab_exit, ++ .receive = ab_receive, ++ .transmit = ab_transmit, ++ .port_leave = ab_port_leave, ++}; ++ ++static struct team_mode ab_mode = { ++ .kind = "activebackup", ++ .owner = THIS_MODULE, ++ .priv_size = sizeof(struct ab_priv), ++ .ops = &ab_mode_ops, ++}; ++ ++static int __init ab_init_module(void) ++{ ++ return team_mode_register(&ab_mode); ++} ++ ++static void __exit ab_cleanup_module(void) ++{ ++ team_mode_unregister(&ab_mode); ++} ++ ++module_init(ab_init_module); ++module_exit(ab_cleanup_module); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Jiri Pirko "); ++MODULE_DESCRIPTION("Active-backup mode for team"); ++MODULE_ALIAS("team-mode-activebackup"); +diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c +new file mode 100644 +index 0000000..a0e8f80 +--- /dev/null ++++ b/drivers/net/team/team_mode_roundrobin.c +@@ -0,0 +1,107 @@ ++/* ++ * net/drivers/team/team_mode_roundrobin.c - Round-robin mode for team ++ * Copyright (c) 2011 Jiri Pirko ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rr_priv { ++ unsigned int sent_packets; ++}; ++ ++static struct rr_priv *rr_priv(struct team *team) ++{ ++ return (struct rr_priv *) &team->mode_priv; ++} ++ ++static struct team_port *__get_first_port_up(struct team *team, ++ struct team_port *port) ++{ ++ struct team_port *cur; ++ ++ if (port->linkup) ++ return port; ++ cur = port; ++ list_for_each_entry_continue_rcu(cur, &team->port_list, list) ++ if (cur->linkup) ++ return cur; ++ list_for_each_entry_rcu(cur, &team->port_list, list) { ++ if (cur == port) ++ break; ++ if (cur->linkup) ++ return cur; ++ } ++ return NULL; ++} ++ ++static bool rr_transmit(struct team *team, struct sk_buff *skb) ++{ ++ struct team_port *port; ++ int port_index; ++ ++ port_index = rr_priv(team)->sent_packets++ % team->port_count; ++ port = team_get_port_by_index_rcu(team, port_index); ++ port = __get_first_port_up(team, port); ++ if (unlikely(!port)) ++ goto drop; ++ skb->dev = port->dev; ++ if (dev_queue_xmit(skb)) ++ return false; ++ return true; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ return false; ++} ++ ++static int rr_port_enter(struct team *team, struct team_port *port) ++{ ++ return team_port_set_team_mac(port); ++} ++ ++static void rr_port_change_mac(struct team *team, struct team_port *port) ++{ ++ team_port_set_team_mac(port); ++} ++ ++static const struct team_mode_ops rr_mode_ops = { ++ .transmit = rr_transmit, ++ .port_enter = rr_port_enter, ++ .port_change_mac = rr_port_change_mac, ++}; ++ ++static struct team_mode rr_mode = { ++ .kind = "roundrobin", ++ .owner = THIS_MODULE, ++ .priv_size = sizeof(struct rr_priv), ++ .ops = &rr_mode_ops, ++}; ++ ++static int __init rr_init_module(void) ++{ ++ return team_mode_register(&rr_mode); ++} ++ ++static void __exit rr_cleanup_module(void) ++{ ++ team_mode_unregister(&rr_mode); ++} ++ ++module_init(rr_init_module); ++module_exit(rr_cleanup_module); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Jiri Pirko "); ++MODULE_DESCRIPTION("Round-robin mode for team"); ++MODULE_ALIAS("team-mode-roundrobin"); +diff --git a/include/linux/Kbuild b/include/linux/Kbuild +index 619b565..0b091b3 100644 +--- a/include/linux/Kbuild ++++ b/include/linux/Kbuild +@@ -185,6 +185,7 @@ header-y += if_pppol2tp.h + header-y += if_pppox.h + header-y += if_slip.h + header-y += if_strip.h ++header-y += if_team.h + header-y += if_tr.h + header-y += if_tun.h + header-y += if_tunnel.h +diff --git a/include/linux/if.h b/include/linux/if.h +index db20bd4..06b6ef6 100644 +--- a/include/linux/if.h ++++ b/include/linux/if.h +@@ -79,6 +79,7 @@ + #define IFF_TX_SKB_SHARING 0x10000 /* The interface supports sharing + * skbs on transmit */ + #define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ ++#define IFF_TEAM_PORT 0x40000 /* device used as team port */ + + #define IF_GET_IFACE 0x0001 /* for querying only */ + #define IF_GET_PROTO 0x0002 +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +new file mode 100644 +index 0000000..14f6388 +--- /dev/null ++++ b/include/linux/if_team.h +@@ -0,0 +1,242 @@ ++/* ++ * include/linux/if_team.h - Network team device driver header ++ * Copyright (c) 2011 Jiri Pirko ++ * ++ * 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. ++ */ ++ ++#ifndef _LINUX_IF_TEAM_H_ ++#define _LINUX_IF_TEAM_H_ ++ ++#ifdef __KERNEL__ ++ ++struct team_pcpu_stats { ++ u64 rx_packets; ++ u64 rx_bytes; ++ u64 rx_multicast; ++ u64 tx_packets; ++ u64 tx_bytes; ++ struct u64_stats_sync syncp; ++ u32 rx_dropped; ++ u32 tx_dropped; ++}; ++ ++struct team; ++ ++struct team_port { ++ struct net_device *dev; ++ struct hlist_node hlist; /* node in hash list */ ++ struct list_head list; /* node in ordinary list */ ++ struct team *team; ++ int index; ++ ++ /* ++ * A place for storing original values of the device before it ++ * become a port. ++ */ ++ struct { ++ unsigned char dev_addr[MAX_ADDR_LEN]; ++ unsigned int mtu; ++ } orig; ++ ++ bool linkup; ++ u32 speed; ++ u8 duplex; ++ ++ struct rcu_head rcu; ++}; ++ ++struct team_mode_ops { ++ int (*init)(struct team *team); ++ void (*exit)(struct team *team); ++ rx_handler_result_t (*receive)(struct team *team, ++ struct team_port *port, ++ struct sk_buff *skb); ++ bool (*transmit)(struct team *team, struct sk_buff *skb); ++ int (*port_enter)(struct team *team, struct team_port *port); ++ void (*port_leave)(struct team *team, struct team_port *port); ++ void (*port_change_mac)(struct team *team, struct team_port *port); ++}; ++ ++enum team_option_type { ++ TEAM_OPTION_TYPE_U32, ++ TEAM_OPTION_TYPE_STRING, ++}; ++ ++struct team_option { ++ struct list_head list; ++ const char *name; ++ enum team_option_type type; ++ int (*getter)(struct team *team, void *arg); ++ int (*setter)(struct team *team, void *arg); ++}; ++ ++struct team_mode { ++ struct list_head list; ++ const char *kind; ++ struct module *owner; ++ size_t priv_size; ++ const struct team_mode_ops *ops; ++}; ++ ++#define TEAM_PORT_HASHBITS 4 ++#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS) ++ ++#define TEAM_MODE_PRIV_LONGS 4 ++#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS) ++ ++struct team { ++ struct net_device *dev; /* associated netdevice */ ++ struct team_pcpu_stats __percpu *pcpu_stats; ++ ++ spinlock_t lock; /* used for overall locking, e.g. port lists write */ ++ ++ /* ++ * port lists with port count ++ */ ++ int port_count; ++ struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES]; ++ struct list_head port_list; ++ ++ struct list_head option_list; ++ ++ const struct team_mode *mode; ++ struct team_mode_ops ops; ++ long mode_priv[TEAM_MODE_PRIV_LONGS]; ++}; ++ ++static inline struct hlist_head *team_port_index_hash(struct team *team, ++ int port_index) ++{ ++ return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; ++} ++ ++static inline struct team_port *team_get_port_by_index(struct team *team, ++ int port_index) ++{ ++ struct hlist_node *p; ++ struct team_port *port; ++ struct hlist_head *head = team_port_index_hash(team, port_index); ++ ++ hlist_for_each_entry(port, p, head, hlist) ++ if (port->index == port_index) ++ return port; ++ return NULL; ++} ++static inline struct team_port *team_get_port_by_index_rcu(struct team *team, ++ int port_index) ++{ ++ struct hlist_node *p; ++ struct team_port *port; ++ struct hlist_head *head = team_port_index_hash(team, port_index); ++ ++ hlist_for_each_entry_rcu(port, p, head, hlist) ++ if (port->index == port_index) ++ return port; ++ return NULL; ++} ++ ++extern int team_port_set_team_mac(struct team_port *port); ++extern void team_options_register(struct team *team, ++ struct team_option *option, ++ size_t option_count); ++extern void team_options_unregister(struct team *team, ++ struct team_option *option, ++ size_t option_count); ++extern int team_mode_register(struct team_mode *mode); ++extern int team_mode_unregister(struct team_mode *mode); ++ ++#endif /* __KERNEL__ */ ++ ++#define TEAM_STRING_MAX_LEN 32 ++ ++/********************************** ++ * NETLINK_GENERIC netlink family. ++ **********************************/ ++ ++enum { ++ TEAM_CMD_NOOP, ++ TEAM_CMD_OPTIONS_SET, ++ TEAM_CMD_OPTIONS_GET, ++ TEAM_CMD_PORT_LIST_GET, ++ ++ __TEAM_CMD_MAX, ++ TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1), ++}; ++ ++enum { ++ TEAM_ATTR_UNSPEC, ++ TEAM_ATTR_TEAM_IFINDEX, /* u32 */ ++ TEAM_ATTR_LIST_OPTION, /* nest */ ++ TEAM_ATTR_LIST_PORT, /* nest */ ++ ++ __TEAM_ATTR_MAX, ++ TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1, ++}; ++ ++/* Nested layout of get/set msg: ++ * ++ * [TEAM_ATTR_LIST_OPTION] ++ * [TEAM_ATTR_ITEM_OPTION] ++ * [TEAM_ATTR_OPTION_*], ... ++ * [TEAM_ATTR_ITEM_OPTION] ++ * [TEAM_ATTR_OPTION_*], ... ++ * ... ++ * [TEAM_ATTR_LIST_PORT] ++ * [TEAM_ATTR_ITEM_PORT] ++ * [TEAM_ATTR_PORT_*], ... ++ * [TEAM_ATTR_ITEM_PORT] ++ * [TEAM_ATTR_PORT_*], ... ++ * ... ++ */ ++ ++enum { ++ TEAM_ATTR_ITEM_OPTION_UNSPEC, ++ TEAM_ATTR_ITEM_OPTION, /* nest */ ++ ++ __TEAM_ATTR_ITEM_OPTION_MAX, ++ TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1, ++}; ++ ++enum { ++ TEAM_ATTR_OPTION_UNSPEC, ++ TEAM_ATTR_OPTION_NAME, /* string */ ++ TEAM_ATTR_OPTION_CHANGED, /* flag */ ++ TEAM_ATTR_OPTION_TYPE, /* u8 */ ++ TEAM_ATTR_OPTION_DATA, /* dynamic */ ++ ++ __TEAM_ATTR_OPTION_MAX, ++ TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, ++}; ++ ++enum { ++ TEAM_ATTR_ITEM_PORT_UNSPEC, ++ TEAM_ATTR_ITEM_PORT, /* nest */ ++ ++ __TEAM_ATTR_ITEM_PORT_MAX, ++ TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1, ++}; ++ ++enum { ++ TEAM_ATTR_PORT_UNSPEC, ++ TEAM_ATTR_PORT_IFINDEX, /* u32 */ ++ TEAM_ATTR_PORT_CHANGED, /* flag */ ++ TEAM_ATTR_PORT_LINKUP, /* flag */ ++ TEAM_ATTR_PORT_SPEED, /* u32 */ ++ TEAM_ATTR_PORT_DUPLEX, /* u8 */ ++ ++ __TEAM_ATTR_PORT_MAX, ++ TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, ++}; ++ ++/* ++ * NETLINK_GENERIC related info ++ */ ++#define TEAM_GENL_NAME "team" ++#define TEAM_GENL_VERSION 0x1 ++#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event" ++ ++#endif /* _LINUX_IF_TEAM_H_ */ diff --git a/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch b/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch new file mode 100644 index 000000000..3aea3caeb --- /dev/null +++ b/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch @@ -0,0 +1,49 @@ +From: Jiri Pirko +Date: Wed, 16 Nov 2011 11:55:54 +0000 +Subject: [02/23] team: Do not hold rcu_read_lock when running netlink cmds + +commit 8c0713a57482ebfadef197c856a38af3a55444c6 upstream. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 60672bb..e5390c7 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1043,8 +1043,7 @@ err_msg_put: + + /* + * Netlink cmd functions should be locked by following two functions. +- * To ensure team_uninit would not be called in between, hold rcu_read_lock +- * all the time. ++ * Since dev gets held here, that ensures dev won't disappear in between. + */ + static struct team *team_nl_team_get(struct genl_info *info) + { +@@ -1057,10 +1056,10 @@ static struct team *team_nl_team_get(struct genl_info *info) + return NULL; + + ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]); +- rcu_read_lock(); +- dev = dev_get_by_index_rcu(net, ifindex); ++ dev = dev_get_by_index(net, ifindex); + if (!dev || dev->netdev_ops != &team_netdev_ops) { +- rcu_read_unlock(); ++ if (dev) ++ dev_put(dev); + return NULL; + } + +@@ -1072,7 +1071,7 @@ static struct team *team_nl_team_get(struct genl_info *info) + static void team_nl_team_put(struct team *team) + { + spin_unlock(&team->lock); +- rcu_read_unlock(); ++ dev_put(team->dev); + } + + static int team_nl_send_generic(struct genl_info *info, struct team *team, diff --git a/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch b/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch new file mode 100644 index 000000000..67f740f4f --- /dev/null +++ b/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch @@ -0,0 +1,149 @@ +From: Jiri Pirko +Date: Wed, 16 Nov 2011 11:09:08 +0000 +Subject: [03/23] team: convert overall spinlock to mutex + +commit 61dc3461b9549bc10a2f16d254250680cadafcce upstream. + +No need to have spinlock for this purpose. So convert this to mutex and +avoid current schedule while atomic problems in netlink code. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 32 ++++++++++++++++---------------- + include/linux/if_team.h | 2 +- + 2 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index e5390c7..7db219c 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -443,9 +443,9 @@ static void __team_compute_features(struct team *team) + + static void team_compute_features(struct team *team) + { +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + __team_compute_features(team); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + } + + static int team_port_enter(struct team *team, struct team_port *port) +@@ -647,7 +647,7 @@ static int team_init(struct net_device *dev) + int i; + + team->dev = dev; +- spin_lock_init(&team->lock); ++ mutex_init(&team->lock); + + team->pcpu_stats = alloc_percpu(struct team_pcpu_stats); + if (!team->pcpu_stats) +@@ -672,13 +672,13 @@ static void team_uninit(struct net_device *dev) + struct team_port *port; + struct team_port *tmp; + +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + list_for_each_entry_safe(port, tmp, &team->port_list, list) + team_port_del(team, port->dev); + + __team_change_mode(team, NULL); /* cleanup */ + __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + } + + static void team_destructor(struct net_device *dev) +@@ -784,7 +784,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) + * Alhough this is reader, it's guarded by team lock. It's not possible + * to traverse list in reverse under rcu_read_lock + */ +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + list_for_each_entry(port, &team->port_list, list) { + err = dev_set_mtu(port->dev, new_mtu); + if (err) { +@@ -793,7 +793,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) + goto unwind; + } + } +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + + dev->mtu = new_mtu; + +@@ -802,7 +802,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) + unwind: + list_for_each_entry_continue_reverse(port, &team->port_list, list) + dev_set_mtu(port->dev, dev->mtu); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + + return err; + } +@@ -880,9 +880,9 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev) + struct team *team = netdev_priv(dev); + int err; + +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + err = team_port_add(team, port_dev); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + return err; + } + +@@ -891,9 +891,9 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) + struct team *team = netdev_priv(dev); + int err; + +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + err = team_port_del(team, port_dev); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + return err; + } + +@@ -1064,13 +1064,13 @@ static struct team *team_nl_team_get(struct genl_info *info) + } + + team = netdev_priv(dev); +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + return team; + } + + static void team_nl_team_put(struct team *team) + { +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + dev_put(team->dev); + } + +@@ -1486,9 +1486,9 @@ static void team_port_change_check(struct team_port *port, bool linkup) + { + struct team *team = port->team; + +- spin_lock(&team->lock); ++ mutex_lock(&team->lock); + __team_port_change_check(port, linkup); +- spin_unlock(&team->lock); ++ mutex_unlock(&team->lock); + } + + /************************************ +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 14f6388..a6eac12 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -92,7 +92,7 @@ struct team { + struct net_device *dev; /* associated netdevice */ + struct team_pcpu_stats __percpu *pcpu_stats; + +- spinlock_t lock; /* used for overall locking, e.g. port lists write */ ++ struct mutex lock; /* used for overall locking, e.g. port lists write */ + + /* + * port lists with port count diff --git a/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch b/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch new file mode 100644 index 000000000..24b65c675 --- /dev/null +++ b/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch @@ -0,0 +1,189 @@ +From: Jiri Pirko +Date: Wed, 16 Nov 2011 11:09:09 +0000 +Subject: [04/23] team: replicate options on register + +commit 358b838291f618278080bbed435b755f9b46748e upstream. + +Since multiple team instances are putting defined options into their +option list, during register each option must be cloned before added +into list. This resolves uncool memory corruptions when using multiple +teams. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 76 +++++++++++++++++++++++++---- + drivers/net/team/team_mode_activebackup.c | 5 +- + include/linux/if_team.h | 8 +-- + 3 files changed, 72 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 7db219c..f309274 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -80,30 +80,78 @@ EXPORT_SYMBOL(team_port_set_team_mac); + * Options handling + *******************/ + +-void team_options_register(struct team *team, struct team_option *option, +- size_t option_count) ++struct team_option *__team_find_option(struct team *team, const char *opt_name) ++{ ++ struct team_option *option; ++ ++ list_for_each_entry(option, &team->option_list, list) { ++ if (strcmp(option->name, opt_name) == 0) ++ return option; ++ } ++ return NULL; ++} ++ ++int team_options_register(struct team *team, ++ const struct team_option *option, ++ size_t option_count) + { + int i; ++ struct team_option *dst_opts[option_count]; ++ int err; ++ ++ memset(dst_opts, 0, sizeof(dst_opts)); ++ for (i = 0; i < option_count; i++, option++) { ++ struct team_option *dst_opt; ++ ++ if (__team_find_option(team, option->name)) { ++ err = -EEXIST; ++ goto rollback; ++ } ++ dst_opt = kmalloc(sizeof(*option), GFP_KERNEL); ++ if (!dst_opt) { ++ err = -ENOMEM; ++ goto rollback; ++ } ++ memcpy(dst_opt, option, sizeof(*option)); ++ dst_opts[i] = dst_opt; ++ } ++ ++ for (i = 0; i < option_count; i++) ++ list_add_tail(&dst_opts[i]->list, &team->option_list); + +- for (i = 0; i < option_count; i++, option++) +- list_add_tail(&option->list, &team->option_list); ++ return 0; ++ ++rollback: ++ for (i = 0; i < option_count; i++) ++ kfree(dst_opts[i]); ++ ++ return err; + } ++ + EXPORT_SYMBOL(team_options_register); + + static void __team_options_change_check(struct team *team, + struct team_option *changed_option); + + static void __team_options_unregister(struct team *team, +- struct team_option *option, ++ const struct team_option *option, + size_t option_count) + { + int i; + +- for (i = 0; i < option_count; i++, option++) +- list_del(&option->list); ++ for (i = 0; i < option_count; i++, option++) { ++ struct team_option *del_opt; ++ ++ del_opt = __team_find_option(team, option->name); ++ if (del_opt) { ++ list_del(&del_opt->list); ++ kfree(del_opt); ++ } ++ } + } + +-void team_options_unregister(struct team *team, struct team_option *option, ++void team_options_unregister(struct team *team, ++ const struct team_option *option, + size_t option_count) + { + __team_options_unregister(team, option, option_count); +@@ -632,7 +680,7 @@ static int team_mode_option_set(struct team *team, void *arg) + return team_change_mode(team, *str); + } + +-static struct team_option team_options[] = { ++static const struct team_option team_options[] = { + { + .name = "mode", + .type = TEAM_OPTION_TYPE_STRING, +@@ -645,6 +693,7 @@ static int team_init(struct net_device *dev) + { + struct team *team = netdev_priv(dev); + int i; ++ int err; + + team->dev = dev; + mutex_init(&team->lock); +@@ -660,10 +709,17 @@ static int team_init(struct net_device *dev) + team_adjust_ops(team); + + INIT_LIST_HEAD(&team->option_list); +- team_options_register(team, team_options, ARRAY_SIZE(team_options)); ++ err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); ++ if (err) ++ goto err_options_register; + netif_carrier_off(dev); + + return 0; ++ ++err_options_register: ++ free_percpu(team->pcpu_stats); ++ ++ return err; + } + + static void team_uninit(struct net_device *dev) +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +index 6fe920c..b344275 100644 +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -83,7 +83,7 @@ static int ab_active_port_set(struct team *team, void *arg) + return -ENOENT; + } + +-static struct team_option ab_options[] = { ++static const struct team_option ab_options[] = { + { + .name = "activeport", + .type = TEAM_OPTION_TYPE_U32, +@@ -94,8 +94,7 @@ static struct team_option ab_options[] = { + + int ab_init(struct team *team) + { +- team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); +- return 0; ++ return team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); + } + + void ab_exit(struct team *team) +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index a6eac12..828181f 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -140,11 +140,11 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team, + } + + extern int team_port_set_team_mac(struct team_port *port); +-extern void team_options_register(struct team *team, +- struct team_option *option, +- size_t option_count); ++extern int team_options_register(struct team *team, ++ const struct team_option *option, ++ size_t option_count); + extern void team_options_unregister(struct team *team, +- struct team_option *option, ++ const struct team_option *option, + size_t option_count); + extern int team_mode_register(struct team_mode *mode); + extern int team_mode_unregister(struct team_mode *mode); diff --git a/debian/patches/features/all/team/0005-team-add-fix_features.patch b/debian/patches/features/all/team/0005-team-add-fix_features.patch new file mode 100644 index 000000000..85a504ce5 --- /dev/null +++ b/debian/patches/features/all/team/0005-team-add-fix_features.patch @@ -0,0 +1,54 @@ +From: Jiri Pirko +Date: Thu, 17 Nov 2011 04:16:04 +0000 +Subject: [05/23] team: add fix_features + +commit 234a8fd49d086f5a3debb379bfdf4e6b51f0c0e2 upstream. + +do fix features in similar way as bonding code does + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index f309274..5b169c1 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -953,6 +953,27 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) + return err; + } + ++static netdev_features_t team_fix_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct team_port *port; ++ struct team *team = netdev_priv(dev); ++ netdev_features_t mask; ++ ++ mask = features; ++ features &= ~NETIF_F_ONE_FOR_ALL; ++ features |= NETIF_F_ALL_FOR_ALL; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ features = netdev_increment_features(features, ++ port->dev->features, ++ mask); ++ } ++ rcu_read_unlock(); ++ return features; ++} ++ + static const struct net_device_ops team_netdev_ops = { + .ndo_init = team_init, + .ndo_uninit = team_uninit, +@@ -968,6 +989,7 @@ static const struct net_device_ops team_netdev_ops = { + .ndo_vlan_rx_kill_vid = team_vlan_rx_kill_vid, + .ndo_add_slave = team_add_slave, + .ndo_del_slave = team_del_slave, ++ .ndo_fix_features = team_fix_features, + }; + + diff --git a/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch b/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch new file mode 100644 index 000000000..2abd0fe1c --- /dev/null +++ b/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch @@ -0,0 +1,50 @@ +From: Jiri Pirko +Date: Thu, 17 Nov 2011 04:16:05 +0000 +Subject: [06/23] team: avoid using variable-length array + +commit 2bba19fff8d09bf19df5d5e2de7188d65de67c3e upstream. + +Apparently using variable-length array is not correct +(https://lkml.org/lkml/2011/10/23/25). So remove it. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 5b169c1..c48ef19 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -96,10 +96,13 @@ int team_options_register(struct team *team, + size_t option_count) + { + int i; +- struct team_option *dst_opts[option_count]; ++ struct team_option **dst_opts; + int err; + +- memset(dst_opts, 0, sizeof(dst_opts)); ++ dst_opts = kzalloc(sizeof(struct team_option *) * option_count, ++ GFP_KERNEL); ++ if (!dst_opts) ++ return -ENOMEM; + for (i = 0; i < option_count; i++, option++) { + struct team_option *dst_opt; + +@@ -119,12 +122,14 @@ int team_options_register(struct team *team, + for (i = 0; i < option_count; i++) + list_add_tail(&dst_opts[i]->list, &team->option_list); + ++ kfree(dst_opts); + return 0; + + rollback: + for (i = 0; i < option_count; i++) + kfree(dst_opts[i]); + ++ kfree(dst_opts); + return err; + } + diff --git a/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch b/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch new file mode 100644 index 000000000..7680fbdfd --- /dev/null +++ b/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch @@ -0,0 +1,38 @@ +From: Jiri Pirko +Date: Thu, 17 Nov 2011 06:32:37 +0000 +Subject: [07/23] team: replace kmalloc+memcpy by kmemdup + +commit f8a15af093b19b86d56933c8757cee298d0f32a8 upstream. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index c48ef19..064155d 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -104,19 +104,15 @@ int team_options_register(struct team *team, + if (!dst_opts) + return -ENOMEM; + for (i = 0; i < option_count; i++, option++) { +- struct team_option *dst_opt; +- + if (__team_find_option(team, option->name)) { + err = -EEXIST; + goto rollback; + } +- dst_opt = kmalloc(sizeof(*option), GFP_KERNEL); +- if (!dst_opt) { ++ dst_opts[i] = kmemdup(option, sizeof(*option), GFP_KERNEL); ++ if (!dst_opts[i]) { + err = -ENOMEM; + goto rollback; + } +- memcpy(dst_opt, option, sizeof(*option)); +- dst_opts[i] = dst_opt; + } + + for (i = 0; i < option_count; i++) diff --git a/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch b/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch new file mode 100644 index 000000000..9bd5f39de --- /dev/null +++ b/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch @@ -0,0 +1,28 @@ +From: Eric Dumazet +Date: Wed, 23 Nov 2011 07:09:32 +0000 +Subject: [08/23] net: treewide use of RCU_INIT_POINTER + +commit 2cfa5a0471fef43fda0b7bd87e3a5e4dbadb7809 upstream. + +rcu_assign_pointer(ptr, NULL) can be safely replaced by +RCU_INIT_POINTER(ptr, NULL) + +(old rcu_assign_pointer() macro was testing the NULL value and could +omit the smp_wmb(), but this had to be removed because of compiler +warnings) + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +[bwh: Restrict to drivers/net/team/] +--- +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -56,7 +56,7 @@ drop: + static void ab_port_leave(struct team *team, struct team_port *port) + { + if (ab_priv(team)->active_port == port) +- rcu_assign_pointer(ab_priv(team)->active_port, NULL); ++ RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); + } + + static int ab_active_port_get(struct team *team, void *arg) diff --git a/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch b/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch new file mode 100644 index 000000000..f30b01ec2 --- /dev/null +++ b/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch @@ -0,0 +1,132 @@ +From: Jiri Pirko +Date: Thu, 8 Dec 2011 04:11:17 +0000 +Subject: [09/23] net: introduce vlan_vid_[add/del] and use them instead of + direct [add/kill]_vid ndo calls + +commit 87002b03baabd2b8f6281ab6411ed88d24958de1 upstream. + +This patch adds wrapper for ndo_vlan_rx_add_vid/ndo_vlan_rx_kill_vid +functions. Check for NETIF_F_HW_VLAN_FILTER feature is done in this +wrapper. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +[bwh: Drop changes to bonding, macvlan, vlan; assume + ndo_vlan_rx_{add,kill}_vid still return void] +--- +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -906,15 +907,26 @@ + { + struct team *team = netdev_priv(dev); + struct team_port *port; ++ int err; + +- rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) { +- const struct net_device_ops *ops = port->dev->netdev_ops; +- +- if (ops->ndo_vlan_rx_add_vid) +- ops->ndo_vlan_rx_add_vid(port->dev, vid); ++ /* ++ * Alhough this is reader, it's guarded by team lock. It's not possible ++ * to traverse list in reverse under rcu_read_lock ++ */ ++ mutex_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) { ++ err = vlan_vid_add(port->dev, vid); ++ if (err) ++ goto unwind; + } +- rcu_read_unlock(); ++ mutex_unlock(&team->lock); ++ ++ return; ++ ++unwind: ++ list_for_each_entry_continue_reverse(port, &team->port_list, list) ++ vlan_vid_del(port->dev, vid); ++ mutex_unlock(&team->lock); + } + + static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) +@@ -923,12 +935,8 @@ + struct team_port *port; + + rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) { +- const struct net_device_ops *ops = port->dev->netdev_ops; +- +- if (ops->ndo_vlan_rx_kill_vid) +- ops->ndo_vlan_rx_kill_vid(port->dev, vid); +- } ++ list_for_each_entry_rcu(port, &team->port_list, list) ++ vlan_vid_del(port->dev, vid); + rcu_read_unlock(); + } + +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -109,6 +109,9 @@ + extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); + extern struct sk_buff *vlan_untag(struct sk_buff *skb); + ++extern int vlan_vid_add(struct net_device *dev, unsigned short vid); ++extern void vlan_vid_del(struct net_device *dev, unsigned short vid); ++ + #else + static inline struct net_device * + __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) +@@ -139,6 +142,15 @@ + { + return skb; + } ++ ++static inline int vlan_vid_add(struct net_device *dev, unsigned short vid) ++{ ++ return 0; ++} ++ ++static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) ++{ ++} + #endif + + /** +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -179,3 +179,26 @@ + kfree_skb(skb); + return NULL; + } ++ ++int vlan_vid_add(struct net_device *dev, unsigned short vid) ++{ ++ const struct net_device_ops *ops = dev->netdev_ops; ++ ++ if ((dev->features & NETIF_F_HW_VLAN_FILTER) && ++ ops->ndo_vlan_rx_add_vid) { ++ ops->ndo_vlan_rx_add_vid(dev, vid); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(vlan_vid_add); ++ ++void vlan_vid_del(struct net_device *dev, unsigned short vid) ++{ ++ const struct net_device_ops *ops = dev->netdev_ops; ++ ++ if ((dev->features & NETIF_F_HW_VLAN_FILTER) && ++ ops->ndo_vlan_rx_kill_vid) { ++ ops->ndo_vlan_rx_kill_vid(dev, vid); ++ } ++} ++EXPORT_SYMBOL(vlan_vid_del); diff --git a/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch b/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch new file mode 100644 index 000000000..f6ebb7e8c --- /dev/null +++ b/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch @@ -0,0 +1,81 @@ +From: Jiri Pirko +Date: Thu, 8 Dec 2011 04:11:19 +0000 +Subject: [10/23] vlan: introduce functions to do mass addition/deletion of vids by + another device + +commit 348a1443cc4303c72cf1ee3b26e476fec8e7b5fa upstream. + +Introduce functions handy to copy vlan ids from one driver's list to +another. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +[bwh: Assume ndo_vlan_rx_add_id still returns void] +--- +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -112,6 +112,10 @@ + extern int vlan_vid_add(struct net_device *dev, unsigned short vid); + extern void vlan_vid_del(struct net_device *dev, unsigned short vid); + ++extern int vlan_vids_add_by_dev(struct net_device *dev, ++ const struct net_device *by_dev); ++extern void vlan_vids_del_by_dev(struct net_device *dev, ++ const struct net_device *by_dev); + #else + static inline struct net_device * + __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) +@@ -151,6 +155,16 @@ + static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) + { + } ++ ++static inline int vlan_vids_add_by_dev(struct net_device *dev, ++ const struct net_device *by_dev) ++{ ++} ++ ++static inline void vlan_vids_del_by_dev(struct net_device *dev, ++ const struct net_device *by_dev) ++{ ++} + #endif + + /** +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -202,3 +202,34 @@ + } + } + EXPORT_SYMBOL(vlan_vid_del); ++ ++int vlan_vids_add_by_dev(struct net_device *dev, ++ const struct net_device *by_dev) ++{ ++ struct vlan_vid_info *vid_info; ++ ++ ASSERT_RTNL(); ++ ++ if (!by_dev->vlan_info) ++ return; ++ ++ list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) { ++ vlan_vid_add(dev, vid_info->vid); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(vlan_vids_add_by_dev); ++ ++void vlan_vids_del_by_dev(struct net_device *dev, ++ const struct net_device *by_dev) ++{ ++ struct vlan_vid_info *vid_info; ++ ++ ASSERT_RTNL(); ++ ++ if (!by_dev->vlan_info) ++ return; ++ ++ list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) ++ vlan_vid_del(dev, vid_info->vid); ++} diff --git a/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch b/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch new file mode 100644 index 000000000..9cbbde450 --- /dev/null +++ b/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch @@ -0,0 +1,53 @@ +From: Jiri Pirko +Date: Thu, 8 Dec 2011 04:11:20 +0000 +Subject: [11/23] team: use vlan_vids_[addr/del]_by_dev + +commit 57459185a19b0246866479522b77cbb9732201d1 upstream. + +So far when vlan id was added to team device befor port was added, this +vid was not added to port's vlan filter. Also after removal, vid stayed +in port device's vlan filter. Benefit of new vlan functions to handle +this work. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 79c2d1b..ed2a862 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -588,6 +588,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + goto err_dev_open; + } + ++ err = vlan_vids_add_by_dev(port_dev, dev); ++ if (err) { ++ netdev_err(dev, "Failed to add vlan ids to device %s\n", ++ portname); ++ goto err_vids_add; ++ } ++ + err = netdev_set_master(port_dev, dev); + if (err) { + netdev_err(dev, "Device %s failed to set master\n", portname); +@@ -615,6 +622,9 @@ err_handler_register: + netdev_set_master(port_dev, NULL); + + err_set_master: ++ vlan_vids_del_by_dev(port_dev, dev); ++ ++err_vids_add: + dev_close(port_dev); + + err_dev_open: +@@ -648,6 +658,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + team_adjust_ops(team); + netdev_rx_handler_unregister(port_dev); + netdev_set_master(port_dev, NULL); ++ vlan_vids_del_by_dev(port_dev, dev); + dev_close(port_dev); + team_port_leave(team, port); + team_port_set_orig_mac(port); diff --git a/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch b/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch new file mode 100644 index 000000000..1e8d7bb6b --- /dev/null +++ b/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch @@ -0,0 +1,371 @@ +From: Jiri Pirko +Date: Tue, 24 Jan 2012 05:16:00 +0000 +Subject: [12/23] team: send only changed options/ports via netlink + +commit b82b9183d4f18f9b8c4bb31f223eb6c79b734eb0 upstream. + +This patch changes event message behaviour to send only updated records +instead of whole list. This fixes bug on which userspace receives non-actual +data in case multiple events occur in row. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 136 +++++++++++++++++++++++++++++++---------------- + include/linux/if_team.h | 10 ++++ + 2 files changed, 100 insertions(+), 46 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index ed2a862..6b678f3 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -92,9 +92,9 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name) + return NULL; + } + +-int team_options_register(struct team *team, +- const struct team_option *option, +- size_t option_count) ++int __team_options_register(struct team *team, ++ const struct team_option *option, ++ size_t option_count) + { + int i; + struct team_option **dst_opts; +@@ -116,8 +116,11 @@ int team_options_register(struct team *team, + } + } + +- for (i = 0; i < option_count; i++) ++ for (i = 0; i < option_count; i++) { ++ dst_opts[i]->changed = true; ++ dst_opts[i]->removed = false; + list_add_tail(&dst_opts[i]->list, &team->option_list); ++ } + + kfree(dst_opts); + return 0; +@@ -130,10 +133,22 @@ rollback: + return err; + } + +-EXPORT_SYMBOL(team_options_register); ++static void __team_options_mark_removed(struct team *team, ++ const struct team_option *option, ++ size_t option_count) ++{ ++ int i; ++ ++ for (i = 0; i < option_count; i++, option++) { ++ struct team_option *del_opt; + +-static void __team_options_change_check(struct team *team, +- struct team_option *changed_option); ++ del_opt = __team_find_option(team, option->name); ++ if (del_opt) { ++ del_opt->changed = true; ++ del_opt->removed = true; ++ } ++ } ++} + + static void __team_options_unregister(struct team *team, + const struct team_option *option, +@@ -152,12 +167,29 @@ static void __team_options_unregister(struct team *team, + } + } + ++static void __team_options_change_check(struct team *team); ++ ++int team_options_register(struct team *team, ++ const struct team_option *option, ++ size_t option_count) ++{ ++ int err; ++ ++ err = __team_options_register(team, option, option_count); ++ if (err) ++ return err; ++ __team_options_change_check(team); ++ return 0; ++} ++EXPORT_SYMBOL(team_options_register); ++ + void team_options_unregister(struct team *team, + const struct team_option *option, + size_t option_count) + { ++ __team_options_mark_removed(team, option, option_count); ++ __team_options_change_check(team); + __team_options_unregister(team, option, option_count); +- __team_options_change_check(team, NULL); + } + EXPORT_SYMBOL(team_options_unregister); + +@@ -176,7 +208,8 @@ static int team_option_set(struct team *team, struct team_option *option, + if (err) + return err; + +- __team_options_change_check(team, option); ++ option->changed = true; ++ __team_options_change_check(team); + return err; + } + +@@ -653,6 +686,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + return -ENOENT; + } + ++ port->removed = true; + __team_port_change_check(port, false); + team_port_list_del_port(team, port); + team_adjust_ops(team); +@@ -1200,10 +1234,9 @@ err_fill: + return err; + } + +-static int team_nl_fill_options_get_changed(struct sk_buff *skb, +- u32 pid, u32 seq, int flags, +- struct team *team, +- struct team_option *changed_option) ++static int team_nl_fill_options_get(struct sk_buff *skb, ++ u32 pid, u32 seq, int flags, ++ struct team *team, bool fillall) + { + struct nlattr *option_list; + void *hdr; +@@ -1223,12 +1256,19 @@ static int team_nl_fill_options_get_changed(struct sk_buff *skb, + struct nlattr *option_item; + long arg; + ++ /* Include only changed options if fill all mode is not on */ ++ if (!fillall && !option->changed) ++ continue; + option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); + if (!option_item) + goto nla_put_failure; + NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); +- if (option == changed_option) ++ if (option->changed) { + NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); ++ option->changed = false; ++ } ++ if (option->removed) ++ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED); + switch (option->type) { + case TEAM_OPTION_TYPE_U32: + NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); +@@ -1255,13 +1295,13 @@ nla_put_failure: + return -EMSGSIZE; + } + +-static int team_nl_fill_options_get(struct sk_buff *skb, +- struct genl_info *info, int flags, +- struct team *team) ++static int team_nl_fill_options_get_all(struct sk_buff *skb, ++ struct genl_info *info, int flags, ++ struct team *team) + { +- return team_nl_fill_options_get_changed(skb, info->snd_pid, +- info->snd_seq, NLM_F_ACK, +- team, NULL); ++ return team_nl_fill_options_get(skb, info->snd_pid, ++ info->snd_seq, NLM_F_ACK, ++ team, true); + } + + static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) +@@ -1273,7 +1313,7 @@ static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) + if (!team) + return -EINVAL; + +- err = team_nl_send_generic(info, team, team_nl_fill_options_get); ++ err = team_nl_send_generic(info, team, team_nl_fill_options_get_all); + + team_nl_team_put(team); + +@@ -1365,10 +1405,10 @@ team_put: + return err; + } + +-static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, +- u32 pid, u32 seq, int flags, +- struct team *team, +- struct team_port *changed_port) ++static int team_nl_fill_port_list_get(struct sk_buff *skb, ++ u32 pid, u32 seq, int flags, ++ struct team *team, ++ bool fillall) + { + struct nlattr *port_list; + void *hdr; +@@ -1387,12 +1427,19 @@ static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, + list_for_each_entry(port, &team->port_list, list) { + struct nlattr *port_item; + ++ /* Include only changed ports if fill all mode is not on */ ++ if (!fillall && !port->changed) ++ continue; + port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); + if (!port_item) + goto nla_put_failure; + NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); +- if (port == changed_port) ++ if (port->changed) { + NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); ++ port->changed = false; ++ } ++ if (port->removed) ++ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED); + if (port->linkup) + NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); + NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); +@@ -1408,13 +1455,13 @@ nla_put_failure: + return -EMSGSIZE; + } + +-static int team_nl_fill_port_list_get(struct sk_buff *skb, +- struct genl_info *info, int flags, +- struct team *team) ++static int team_nl_fill_port_list_get_all(struct sk_buff *skb, ++ struct genl_info *info, int flags, ++ struct team *team) + { +- return team_nl_fill_port_list_get_changed(skb, info->snd_pid, +- info->snd_seq, NLM_F_ACK, +- team, NULL); ++ return team_nl_fill_port_list_get(skb, info->snd_pid, ++ info->snd_seq, NLM_F_ACK, ++ team, true); + } + + static int team_nl_cmd_port_list_get(struct sk_buff *skb, +@@ -1427,7 +1474,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb, + if (!team) + return -EINVAL; + +- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get); ++ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all); + + team_nl_team_put(team); + +@@ -1464,8 +1511,7 @@ static struct genl_multicast_group team_change_event_mcgrp = { + .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, + }; + +-static int team_nl_send_event_options_get(struct team *team, +- struct team_option *changed_option) ++static int team_nl_send_event_options_get(struct team *team) + { + struct sk_buff *skb; + int err; +@@ -1475,8 +1521,7 @@ static int team_nl_send_event_options_get(struct team *team, + if (!skb) + return -ENOMEM; + +- err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team, +- changed_option); ++ err = team_nl_fill_options_get(skb, 0, 0, 0, team, false); + if (err < 0) + goto err_fill; + +@@ -1489,18 +1534,17 @@ err_fill: + return err; + } + +-static int team_nl_send_event_port_list_get(struct team_port *port) ++static int team_nl_send_event_port_list_get(struct team *team) + { + struct sk_buff *skb; + int err; +- struct net *net = dev_net(port->team->dev); ++ struct net *net = dev_net(team->dev); + + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + +- err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0, +- port->team, port); ++ err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false); + if (err < 0) + goto err_fill; + +@@ -1544,12 +1588,11 @@ static void team_nl_fini(void) + * Change checkers + ******************/ + +-static void __team_options_change_check(struct team *team, +- struct team_option *changed_option) ++static void __team_options_change_check(struct team *team) + { + int err; + +- err = team_nl_send_event_options_get(team, changed_option); ++ err = team_nl_send_event_options_get(team); + if (err) + netdev_warn(team->dev, "Failed to send options change via netlink\n"); + } +@@ -1559,9 +1602,10 @@ static void __team_port_change_check(struct team_port *port, bool linkup) + { + int err; + +- if (port->linkup == linkup) ++ if (!port->removed && port->linkup == linkup) + return; + ++ port->changed = true; + port->linkup = linkup; + if (linkup) { + struct ethtool_cmd ecmd; +@@ -1577,7 +1621,7 @@ static void __team_port_change_check(struct team_port *port, bool linkup) + port->duplex = 0; + + send_event: +- err = team_nl_send_event_port_list_get(port); ++ err = team_nl_send_event_port_list_get(port->team); + if (err) + netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", + port->dev->name); +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 828181f..58404b0 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -46,6 +46,10 @@ struct team_port { + u32 speed; + u8 duplex; + ++ /* Custom gennetlink interface related flags */ ++ bool changed; ++ bool removed; ++ + struct rcu_head rcu; + }; + +@@ -72,6 +76,10 @@ struct team_option { + enum team_option_type type; + int (*getter)(struct team *team, void *arg); + int (*setter)(struct team *team, void *arg); ++ ++ /* Custom gennetlink interface related flags */ ++ bool changed; ++ bool removed; + }; + + struct team_mode { +@@ -207,6 +215,7 @@ enum { + TEAM_ATTR_OPTION_CHANGED, /* flag */ + TEAM_ATTR_OPTION_TYPE, /* u8 */ + TEAM_ATTR_OPTION_DATA, /* dynamic */ ++ TEAM_ATTR_OPTION_REMOVED, /* flag */ + + __TEAM_ATTR_OPTION_MAX, + TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, +@@ -227,6 +236,7 @@ enum { + TEAM_ATTR_PORT_LINKUP, /* flag */ + TEAM_ATTR_PORT_SPEED, /* u32 */ + TEAM_ATTR_PORT_DUPLEX, /* u8 */ ++ TEAM_ATTR_PORT_REMOVED, /* flag */ + + __TEAM_ATTR_PORT_MAX, + TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, diff --git a/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch b/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch new file mode 100644 index 000000000..5f8f3a28c --- /dev/null +++ b/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch @@ -0,0 +1,108 @@ +From: "David S. Miller" +Date: Sun, 1 Apr 2012 20:25:18 -0400 +Subject: [13/23] team: Stop using NLA_PUT*(). + +commit 86ebb02dc793058ea17ad647c802b507dafff7cb upstream. + +These macros contain a hidden goto, and are thus extremely error +prone and make code hard to audit. + +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 50 +++++++++++++++++++++++++++++------------------ + 1 file changed, 31 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 8f81805..0db6e66 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1248,7 +1248,8 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + if (IS_ERR(hdr)) + return PTR_ERR(hdr); + +- NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); ++ if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) ++ goto nla_put_failure; + option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION); + if (!option_list) + return -EMSGSIZE; +@@ -1263,24 +1264,31 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); + if (!option_item) + goto nla_put_failure; +- NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); ++ if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name)) ++ goto nla_put_failure; + if (option->changed) { +- NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); ++ if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED)) ++ goto nla_put_failure; + option->changed = false; + } +- if (option->removed) +- NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED); ++ if (option->removed && ++ nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED)) ++ goto nla_put_failure; + switch (option->type) { + case TEAM_OPTION_TYPE_U32: +- NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); ++ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) ++ goto nla_put_failure; + team_option_get(team, option, &arg); +- NLA_PUT_U32(skb, TEAM_ATTR_OPTION_DATA, arg); ++ if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, arg)) ++ goto nla_put_failure; + break; + case TEAM_OPTION_TYPE_STRING: +- NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING); ++ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING)) ++ goto nla_put_failure; + team_option_get(team, option, &arg); +- NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_DATA, +- (char *) arg); ++ if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA, ++ (char *) arg)) ++ goto nla_put_failure; + break; + default: + BUG(); +@@ -1420,7 +1428,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, + if (IS_ERR(hdr)) + return PTR_ERR(hdr); + +- NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); ++ if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) ++ goto nla_put_failure; + port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT); + if (!port_list) + return -EMSGSIZE; +@@ -1434,17 +1443,20 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, + port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); + if (!port_item) + goto nla_put_failure; +- NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); ++ if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) ++ goto nla_put_failure; + if (port->changed) { +- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); ++ if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) ++ goto nla_put_failure; + port->changed = false; + } +- if (port->removed) +- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED); +- if (port->linkup) +- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); +- NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); +- NLA_PUT_U8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex); ++ if ((port->removed && ++ nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || ++ (port->linkup && ++ nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || ++ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->speed) || ++ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex)) ++ goto nla_put_failure; + nla_nest_end(skb, port_item); + } + diff --git a/debian/patches/features/all/team/0014-team-add-binary-option-type.patch b/debian/patches/features/all/team/0014-team-add-binary-option-type.patch new file mode 100644 index 000000000..b1fadec16 --- /dev/null +++ b/debian/patches/features/all/team/0014-team-add-binary-option-type.patch @@ -0,0 +1,124 @@ +From: Jiri Pirko +Date: Wed, 4 Apr 2012 12:16:26 +0000 +Subject: [14/23] team: add binary option type + +commit 2615598fc100451c71b83d06bdf5faead619a40e upstream. + +For transfering generic binary data (e.g. BPF code), introduce new +binary option type. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 30 ++++++++++++++++++++++++++---- + include/linux/if_team.h | 8 ++++++++ + 2 files changed, 34 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 0db6e66..ea96f82 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1145,10 +1145,7 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { + }, + [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, + [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, +- [TEAM_ATTR_OPTION_DATA] = { +- .type = NLA_BINARY, +- .len = TEAM_STRING_MAX_LEN, +- }, ++ [TEAM_ATTR_OPTION_DATA] = { .type = NLA_BINARY }, + }; + + static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) +@@ -1257,6 +1254,7 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + list_for_each_entry(option, &team->option_list, list) { + struct nlattr *option_item; + long arg; ++ struct team_option_binary tbinary; + + /* Include only changed options if fill all mode is not on */ + if (!fillall && !option->changed) +@@ -1290,6 +1288,15 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + (char *) arg)) + goto nla_put_failure; + break; ++ case TEAM_OPTION_TYPE_BINARY: ++ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY)) ++ goto nla_put_failure; ++ arg = (long) &tbinary; ++ team_option_get(team, option, &arg); ++ if (nla_put(skb, TEAM_ATTR_OPTION_DATA, ++ tbinary.data_len, tbinary.data)) ++ goto nla_put_failure; ++ break; + default: + BUG(); + } +@@ -1374,6 +1381,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + case NLA_STRING: + opt_type = TEAM_OPTION_TYPE_STRING; + break; ++ case NLA_BINARY: ++ opt_type = TEAM_OPTION_TYPE_BINARY; ++ break; + default: + goto team_put; + } +@@ -1382,19 +1392,31 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + list_for_each_entry(option, &team->option_list, list) { + long arg; + struct nlattr *opt_data_attr; ++ struct team_option_binary tbinary; ++ int data_len; + + if (option->type != opt_type || + strcmp(option->name, opt_name)) + continue; + opt_found = true; + opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; ++ data_len = nla_len(opt_data_attr); + switch (opt_type) { + case TEAM_OPTION_TYPE_U32: + arg = nla_get_u32(opt_data_attr); + break; + case TEAM_OPTION_TYPE_STRING: ++ if (data_len > TEAM_STRING_MAX_LEN) { ++ err = -EINVAL; ++ goto team_put; ++ } + arg = (long) nla_data(opt_data_attr); + break; ++ case TEAM_OPTION_TYPE_BINARY: ++ tbinary.data_len = data_len; ++ tbinary.data = nla_data(opt_data_attr); ++ arg = (long) &tbinary; ++ break; + default: + BUG(); + } +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 58404b0..41163ac 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -68,6 +68,7 @@ struct team_mode_ops { + enum team_option_type { + TEAM_OPTION_TYPE_U32, + TEAM_OPTION_TYPE_STRING, ++ TEAM_OPTION_TYPE_BINARY, + }; + + struct team_option { +@@ -82,6 +83,13 @@ struct team_option { + bool removed; + }; + ++struct team_option_binary { ++ u32 data_len; ++ void *data; ++}; ++ ++#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg)) ++ + struct team_mode { + struct list_head list; + const char *kind; diff --git a/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch b/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch new file mode 100644 index 000000000..3158c3010 --- /dev/null +++ b/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch @@ -0,0 +1,241 @@ +From: Jiri Pirko +Date: Wed, 4 Apr 2012 12:16:27 +0000 +Subject: [15/23] team: add loadbalance mode + +commit 01d7f30a9f962573b6c91ed520c73fb30658d826 upstream. + +This patch introduces new team mode. It's TX port is selected by +user-set BPF hash function. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/Kconfig | 11 ++ + drivers/net/team/Makefile | 1 + + drivers/net/team/team_mode_loadbalance.c | 188 ++++++++++++++++++++++++++++++ + 3 files changed, 200 insertions(+) + create mode 100644 drivers/net/team/team_mode_loadbalance.c + +diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig +index 248a144..89024d5 100644 +--- a/drivers/net/team/Kconfig ++++ b/drivers/net/team/Kconfig +@@ -40,4 +40,15 @@ config NET_TEAM_MODE_ACTIVEBACKUP + To compile this team mode as a module, choose M here: the module + will be called team_mode_activebackup. + ++config NET_TEAM_MODE_LOADBALANCE ++ tristate "Load-balance mode support" ++ depends on NET_TEAM ++ ---help--- ++ This mode provides load balancing functionality. Tx port selection ++ is done using BPF function set up from userspace (bpf_hash_func ++ option) ++ ++ To compile this team mode as a module, choose M here: the module ++ will be called team_mode_loadbalance. ++ + endif # NET_TEAM +diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile +index 85f2028..fb9f4c1 100644 +--- a/drivers/net/team/Makefile ++++ b/drivers/net/team/Makefile +@@ -5,3 +5,4 @@ + obj-$(CONFIG_NET_TEAM) += team.o + obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o + obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o ++obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o +diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c +new file mode 100644 +index 0000000..ed20f39 +--- /dev/null ++++ b/drivers/net/team/team_mode_loadbalance.c +@@ -0,0 +1,188 @@ ++/* ++ * drivers/net/team/team_mode_loadbalance.c - Load-balancing mode for team ++ * Copyright (c) 2012 Jiri Pirko ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct lb_priv { ++ struct sk_filter __rcu *fp; ++ struct sock_fprog *orig_fprog; ++}; ++ ++static struct lb_priv *lb_priv(struct team *team) ++{ ++ return (struct lb_priv *) &team->mode_priv; ++} ++ ++static bool lb_transmit(struct team *team, struct sk_buff *skb) ++{ ++ struct sk_filter *fp; ++ struct team_port *port; ++ unsigned int hash; ++ int port_index; ++ ++ fp = rcu_dereference(lb_priv(team)->fp); ++ if (unlikely(!fp)) ++ goto drop; ++ hash = SK_RUN_FILTER(fp, skb); ++ port_index = hash % team->port_count; ++ port = team_get_port_by_index_rcu(team, port_index); ++ if (unlikely(!port)) ++ goto drop; ++ skb->dev = port->dev; ++ if (dev_queue_xmit(skb)) ++ return false; ++ return true; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ return false; ++} ++ ++static int lb_bpf_func_get(struct team *team, void *arg) ++{ ++ struct team_option_binary *tbinary = team_optarg_tbinary(arg); ++ ++ memset(tbinary, 0, sizeof(*tbinary)); ++ if (!lb_priv(team)->orig_fprog) ++ return 0; ++ ++ tbinary->data_len = lb_priv(team)->orig_fprog->len * ++ sizeof(struct sock_filter); ++ tbinary->data = lb_priv(team)->orig_fprog->filter; ++ return 0; ++} ++ ++static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, ++ void *data) ++{ ++ struct sock_fprog *fprog; ++ struct sock_filter *filter = (struct sock_filter *) data; ++ ++ if (data_len % sizeof(struct sock_filter)) ++ return -EINVAL; ++ fprog = kmalloc(sizeof(struct sock_fprog), GFP_KERNEL); ++ if (!fprog) ++ return -ENOMEM; ++ fprog->filter = kmemdup(filter, data_len, GFP_KERNEL); ++ if (!fprog->filter) { ++ kfree(fprog); ++ return -ENOMEM; ++ } ++ fprog->len = data_len / sizeof(struct sock_filter); ++ *pfprog = fprog; ++ return 0; ++} ++ ++static void __fprog_destroy(struct sock_fprog *fprog) ++{ ++ kfree(fprog->filter); ++ kfree(fprog); ++} ++ ++static int lb_bpf_func_set(struct team *team, void *arg) ++{ ++ struct team_option_binary *tbinary = team_optarg_tbinary(arg); ++ struct sk_filter *fp = NULL; ++ struct sock_fprog *fprog = NULL; ++ int err; ++ ++ if (tbinary->data_len) { ++ err = __fprog_create(&fprog, tbinary->data_len, ++ tbinary->data); ++ if (err) ++ return err; ++ err = sk_unattached_filter_create(&fp, fprog); ++ if (err) { ++ __fprog_destroy(fprog); ++ return err; ++ } ++ } ++ ++ if (lb_priv(team)->orig_fprog) { ++ /* Clear old filter data */ ++ __fprog_destroy(lb_priv(team)->orig_fprog); ++ sk_unattached_filter_destroy(lb_priv(team)->fp); ++ } ++ ++ rcu_assign_pointer(lb_priv(team)->fp, fp); ++ lb_priv(team)->orig_fprog = fprog; ++ return 0; ++} ++ ++static const struct team_option lb_options[] = { ++ { ++ .name = "bpf_hash_func", ++ .type = TEAM_OPTION_TYPE_BINARY, ++ .getter = lb_bpf_func_get, ++ .setter = lb_bpf_func_set, ++ }, ++}; ++ ++int lb_init(struct team *team) ++{ ++ return team_options_register(team, lb_options, ++ ARRAY_SIZE(lb_options)); ++} ++ ++void lb_exit(struct team *team) ++{ ++ team_options_unregister(team, lb_options, ++ ARRAY_SIZE(lb_options)); ++} ++ ++static int lb_port_enter(struct team *team, struct team_port *port) ++{ ++ return team_port_set_team_mac(port); ++} ++ ++static void lb_port_change_mac(struct team *team, struct team_port *port) ++{ ++ team_port_set_team_mac(port); ++} ++ ++static const struct team_mode_ops lb_mode_ops = { ++ .init = lb_init, ++ .exit = lb_exit, ++ .transmit = lb_transmit, ++ .port_enter = lb_port_enter, ++ .port_change_mac = lb_port_change_mac, ++}; ++ ++static struct team_mode lb_mode = { ++ .kind = "loadbalance", ++ .owner = THIS_MODULE, ++ .priv_size = sizeof(struct lb_priv), ++ .ops = &lb_mode_ops, ++}; ++ ++static int __init lb_init_module(void) ++{ ++ return team_mode_register(&lb_mode); ++} ++ ++static void __exit lb_cleanup_module(void) ++{ ++ team_mode_unregister(&lb_mode); ++} ++ ++module_init(lb_init_module); ++module_exit(lb_cleanup_module); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Jiri Pirko "); ++MODULE_DESCRIPTION("Load-balancing mode for team"); ++MODULE_ALIAS("team-mode-loadbalance"); diff --git a/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch b/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch new file mode 100644 index 000000000..204877e6a --- /dev/null +++ b/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch @@ -0,0 +1,687 @@ +From: Jiri Pirko +Date: Tue, 10 Apr 2012 05:15:42 +0000 +Subject: [16/23] team: add support for per-port options + +commit 80f7c6683fe0e891ef1db7c967d538b5fdddd22c upstream. + +This patch allows to create per-port options. That becomes handy for all +sorts of stuff, for example for userspace driven link-state, 802.3ad +implementation and so on. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 306 +++++++++++++++++++++++------ + drivers/net/team/team_mode_activebackup.c | 14 +- + drivers/net/team/team_mode_loadbalance.c | 28 ++- + include/linux/if_team.h | 30 +-- + 4 files changed, 278 insertions(+), 100 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index ea96f82..eaf8441 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -81,7 +81,16 @@ EXPORT_SYMBOL(team_port_set_team_mac); + * Options handling + *******************/ + +-struct team_option *__team_find_option(struct team *team, const char *opt_name) ++struct team_option_inst { /* One for each option instance */ ++ struct list_head list; ++ struct team_option *option; ++ struct team_port *port; /* != NULL if per-port */ ++ bool changed; ++ bool removed; ++}; ++ ++static struct team_option *__team_find_option(struct team *team, ++ const char *opt_name) + { + struct team_option *option; + +@@ -92,9 +101,121 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name) + return NULL; + } + +-int __team_options_register(struct team *team, +- const struct team_option *option, +- size_t option_count) ++static int __team_option_inst_add(struct team *team, struct team_option *option, ++ struct team_port *port) ++{ ++ struct team_option_inst *opt_inst; ++ ++ opt_inst = kmalloc(sizeof(*opt_inst), GFP_KERNEL); ++ if (!opt_inst) ++ return -ENOMEM; ++ opt_inst->option = option; ++ opt_inst->port = port; ++ opt_inst->changed = true; ++ opt_inst->removed = false; ++ list_add_tail(&opt_inst->list, &team->option_inst_list); ++ return 0; ++} ++ ++static void __team_option_inst_del(struct team_option_inst *opt_inst) ++{ ++ list_del(&opt_inst->list); ++ kfree(opt_inst); ++} ++ ++static void __team_option_inst_del_option(struct team *team, ++ struct team_option *option) ++{ ++ struct team_option_inst *opt_inst, *tmp; ++ ++ list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) { ++ if (opt_inst->option == option) ++ __team_option_inst_del(opt_inst); ++ } ++} ++ ++static int __team_option_inst_add_option(struct team *team, ++ struct team_option *option) ++{ ++ struct team_port *port; ++ int err; ++ ++ if (!option->per_port) ++ return __team_option_inst_add(team, option, 0); ++ ++ list_for_each_entry(port, &team->port_list, list) { ++ err = __team_option_inst_add(team, option, port); ++ if (err) ++ goto inst_del_option; ++ } ++ return 0; ++ ++inst_del_option: ++ __team_option_inst_del_option(team, option); ++ return err; ++} ++ ++static void __team_option_inst_mark_removed_option(struct team *team, ++ struct team_option *option) ++{ ++ struct team_option_inst *opt_inst; ++ ++ list_for_each_entry(opt_inst, &team->option_inst_list, list) { ++ if (opt_inst->option == option) { ++ opt_inst->changed = true; ++ opt_inst->removed = true; ++ } ++ } ++} ++ ++static void __team_option_inst_del_port(struct team *team, ++ struct team_port *port) ++{ ++ struct team_option_inst *opt_inst, *tmp; ++ ++ list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) { ++ if (opt_inst->option->per_port && ++ opt_inst->port == port) ++ __team_option_inst_del(opt_inst); ++ } ++} ++ ++static int __team_option_inst_add_port(struct team *team, ++ struct team_port *port) ++{ ++ struct team_option *option; ++ int err; ++ ++ list_for_each_entry(option, &team->option_list, list) { ++ if (!option->per_port) ++ continue; ++ err = __team_option_inst_add(team, option, port); ++ if (err) ++ goto inst_del_port; ++ } ++ return 0; ++ ++inst_del_port: ++ __team_option_inst_del_port(team, port); ++ return err; ++} ++ ++static void __team_option_inst_mark_removed_port(struct team *team, ++ struct team_port *port) ++{ ++ struct team_option_inst *opt_inst; ++ ++ list_for_each_entry(opt_inst, &team->option_inst_list, list) { ++ if (opt_inst->port == port) { ++ opt_inst->changed = true; ++ opt_inst->removed = true; ++ } ++ } ++} ++ ++static int __team_options_register(struct team *team, ++ const struct team_option *option, ++ size_t option_count) + { + int i; + struct team_option **dst_opts; +@@ -107,26 +228,32 @@ int __team_options_register(struct team *team, + for (i = 0; i < option_count; i++, option++) { + if (__team_find_option(team, option->name)) { + err = -EEXIST; +- goto rollback; ++ goto alloc_rollback; + } + dst_opts[i] = kmemdup(option, sizeof(*option), GFP_KERNEL); + if (!dst_opts[i]) { + err = -ENOMEM; +- goto rollback; ++ goto alloc_rollback; + } + } + + for (i = 0; i < option_count; i++) { +- dst_opts[i]->changed = true; +- dst_opts[i]->removed = false; ++ err = __team_option_inst_add_option(team, dst_opts[i]); ++ if (err) ++ goto inst_rollback; + list_add_tail(&dst_opts[i]->list, &team->option_list); + } + + kfree(dst_opts); + return 0; + +-rollback: +- for (i = 0; i < option_count; i++) ++inst_rollback: ++ for (i--; i >= 0; i--) ++ __team_option_inst_del_option(team, dst_opts[i]); ++ ++ i = option_count - 1; ++alloc_rollback: ++ for (i--; i >= 0; i--) + kfree(dst_opts[i]); + + kfree(dst_opts); +@@ -143,10 +270,8 @@ static void __team_options_mark_removed(struct team *team, + struct team_option *del_opt; + + del_opt = __team_find_option(team, option->name); +- if (del_opt) { +- del_opt->changed = true; +- del_opt->removed = true; +- } ++ if (del_opt) ++ __team_option_inst_mark_removed_option(team, del_opt); + } + } + +@@ -161,6 +286,7 @@ static void __team_options_unregister(struct team *team, + + del_opt = __team_find_option(team, option->name); + if (del_opt) { ++ __team_option_inst_del_option(team, del_opt); + list_del(&del_opt->list); + kfree(del_opt); + } +@@ -193,22 +319,42 @@ void team_options_unregister(struct team *team, + } + EXPORT_SYMBOL(team_options_unregister); + +-static int team_option_get(struct team *team, struct team_option *option, +- void *arg) ++static int team_option_port_add(struct team *team, struct team_port *port) + { +- return option->getter(team, arg); ++ int err; ++ ++ err = __team_option_inst_add_port(team, port); ++ if (err) ++ return err; ++ __team_options_change_check(team); ++ return 0; + } + +-static int team_option_set(struct team *team, struct team_option *option, +- void *arg) ++static void team_option_port_del(struct team *team, struct team_port *port) ++{ ++ __team_option_inst_mark_removed_port(team, port); ++ __team_options_change_check(team); ++ __team_option_inst_del_port(team, port); ++} ++ ++static int team_option_get(struct team *team, ++ struct team_option_inst *opt_inst, ++ struct team_gsetter_ctx *ctx) ++{ ++ return opt_inst->option->getter(team, ctx); ++} ++ ++static int team_option_set(struct team *team, ++ struct team_option_inst *opt_inst, ++ struct team_gsetter_ctx *ctx) + { + int err; + +- err = option->setter(team, arg); ++ err = opt_inst->option->setter(team, ctx); + if (err) + return err; + +- option->changed = true; ++ opt_inst->changed = true; + __team_options_change_check(team); + return err; + } +@@ -642,6 +788,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + goto err_handler_register; + } + ++ err = team_option_port_add(team, port); ++ if (err) { ++ netdev_err(dev, "Device %s failed to add per-port options\n", ++ portname); ++ goto err_option_port_add; ++ } ++ + team_port_list_add_port(team, port); + team_adjust_ops(team); + __team_compute_features(team); +@@ -651,6 +804,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + + return 0; + ++err_option_port_add: ++ netdev_rx_handler_unregister(port_dev); ++ + err_handler_register: + netdev_set_master(port_dev, NULL); + +@@ -690,6 +846,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + __team_port_change_check(port, false); + team_port_list_del_port(team, port); + team_adjust_ops(team); ++ team_option_port_del(team, port); + netdev_rx_handler_unregister(port_dev); + netdev_set_master(port_dev, NULL); + vlan_vids_del_by_dev(port_dev, dev); +@@ -712,19 +869,15 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + + static const char team_no_mode_kind[] = "*NOMODE*"; + +-static int team_mode_option_get(struct team *team, void *arg) ++static int team_mode_option_get(struct team *team, struct team_gsetter_ctx *ctx) + { +- const char **str = arg; +- +- *str = team->mode ? team->mode->kind : team_no_mode_kind; ++ ctx->data.str_val = team->mode ? team->mode->kind : team_no_mode_kind; + return 0; + } + +-static int team_mode_option_set(struct team *team, void *arg) ++static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) + { +- const char **str = arg; +- +- return team_change_mode(team, *str); ++ return team_change_mode(team, ctx->data.str_val); + } + + static const struct team_option team_options[] = { +@@ -756,6 +909,7 @@ static int team_init(struct net_device *dev) + team_adjust_ops(team); + + INIT_LIST_HEAD(&team->option_list); ++ INIT_LIST_HEAD(&team->option_inst_list); + err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); + if (err) + goto err_options_register; +@@ -1238,7 +1392,8 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + { + struct nlattr *option_list; + void *hdr; +- struct team_option *option; ++ struct team_option_inst *opt_inst; ++ int err; + + hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, + TEAM_CMD_OPTIONS_GET); +@@ -1251,50 +1406,61 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + if (!option_list) + return -EMSGSIZE; + +- list_for_each_entry(option, &team->option_list, list) { ++ list_for_each_entry(opt_inst, &team->option_inst_list, list) { + struct nlattr *option_item; +- long arg; +- struct team_option_binary tbinary; ++ struct team_option *option = opt_inst->option; ++ struct team_gsetter_ctx ctx; + + /* Include only changed options if fill all mode is not on */ +- if (!fillall && !option->changed) ++ if (!fillall && !opt_inst->changed) + continue; + option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); + if (!option_item) + goto nla_put_failure; + if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name)) + goto nla_put_failure; +- if (option->changed) { ++ if (opt_inst->changed) { + if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED)) + goto nla_put_failure; +- option->changed = false; ++ opt_inst->changed = false; + } +- if (option->removed && ++ if (opt_inst->removed && + nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED)) + goto nla_put_failure; ++ if (opt_inst->port && ++ nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX, ++ opt_inst->port->dev->ifindex)) ++ goto nla_put_failure; ++ ctx.port = opt_inst->port; + switch (option->type) { + case TEAM_OPTION_TYPE_U32: + if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) + goto nla_put_failure; +- team_option_get(team, option, &arg); +- if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, arg)) ++ err = team_option_get(team, opt_inst, &ctx); ++ if (err) ++ goto errout; ++ if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, ++ ctx.data.u32_val)) + goto nla_put_failure; + break; + case TEAM_OPTION_TYPE_STRING: + if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING)) + goto nla_put_failure; +- team_option_get(team, option, &arg); ++ err = team_option_get(team, opt_inst, &ctx); ++ if (err) ++ goto errout; + if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA, +- (char *) arg)) ++ ctx.data.str_val)) + goto nla_put_failure; + break; + case TEAM_OPTION_TYPE_BINARY: + if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY)) + goto nla_put_failure; +- arg = (long) &tbinary; +- team_option_get(team, option, &arg); ++ err = team_option_get(team, opt_inst, &ctx); ++ if (err) ++ goto errout; + if (nla_put(skb, TEAM_ATTR_OPTION_DATA, +- tbinary.data_len, tbinary.data)) ++ ctx.data.bin_val.len, ctx.data.bin_val.ptr)) + goto nla_put_failure; + break; + default: +@@ -1307,8 +1473,10 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + return genlmsg_end(skb, hdr); + + nla_put_failure: ++ err = -EMSGSIZE; ++errout: + genlmsg_cancel(skb, hdr); +- return -EMSGSIZE; ++ return err; + } + + static int team_nl_fill_options_get_all(struct sk_buff *skb, +@@ -1354,9 +1522,11 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + } + + nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { +- struct nlattr *mode_attrs[TEAM_ATTR_OPTION_MAX + 1]; ++ struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; ++ struct nlattr *attr_port_ifindex; + enum team_option_type opt_type; +- struct team_option *option; ++ int opt_port_ifindex = 0; /* != 0 for per-port options */ ++ struct team_option_inst *opt_inst; + char *opt_name; + bool opt_found = false; + +@@ -1364,17 +1534,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + err = -EINVAL; + goto team_put; + } +- err = nla_parse_nested(mode_attrs, TEAM_ATTR_OPTION_MAX, ++ err = nla_parse_nested(opt_attrs, TEAM_ATTR_OPTION_MAX, + nl_option, team_nl_option_policy); + if (err) + goto team_put; +- if (!mode_attrs[TEAM_ATTR_OPTION_NAME] || +- !mode_attrs[TEAM_ATTR_OPTION_TYPE] || +- !mode_attrs[TEAM_ATTR_OPTION_DATA]) { ++ if (!opt_attrs[TEAM_ATTR_OPTION_NAME] || ++ !opt_attrs[TEAM_ATTR_OPTION_TYPE] || ++ !opt_attrs[TEAM_ATTR_OPTION_DATA]) { + err = -EINVAL; + goto team_put; + } +- switch (nla_get_u8(mode_attrs[TEAM_ATTR_OPTION_TYPE])) { ++ switch (nla_get_u8(opt_attrs[TEAM_ATTR_OPTION_TYPE])) { + case NLA_U32: + opt_type = TEAM_OPTION_TYPE_U32; + break; +@@ -1388,39 +1558,47 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + goto team_put; + } + +- opt_name = nla_data(mode_attrs[TEAM_ATTR_OPTION_NAME]); +- list_for_each_entry(option, &team->option_list, list) { +- long arg; ++ opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]); ++ attr_port_ifindex = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX]; ++ if (attr_port_ifindex) ++ opt_port_ifindex = nla_get_u32(attr_port_ifindex); ++ ++ list_for_each_entry(opt_inst, &team->option_inst_list, list) { ++ struct team_option *option = opt_inst->option; + struct nlattr *opt_data_attr; +- struct team_option_binary tbinary; ++ struct team_gsetter_ctx ctx; + int data_len; ++ int tmp_ifindex; + ++ tmp_ifindex = opt_inst->port ? ++ opt_inst->port->dev->ifindex : 0; + if (option->type != opt_type || +- strcmp(option->name, opt_name)) ++ strcmp(option->name, opt_name) || ++ tmp_ifindex != opt_port_ifindex) + continue; + opt_found = true; +- opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; ++ opt_data_attr = opt_attrs[TEAM_ATTR_OPTION_DATA]; + data_len = nla_len(opt_data_attr); ++ ctx.port = opt_inst->port; + switch (opt_type) { + case TEAM_OPTION_TYPE_U32: +- arg = nla_get_u32(opt_data_attr); ++ ctx.data.u32_val = nla_get_u32(opt_data_attr); + break; + case TEAM_OPTION_TYPE_STRING: + if (data_len > TEAM_STRING_MAX_LEN) { + err = -EINVAL; + goto team_put; + } +- arg = (long) nla_data(opt_data_attr); ++ ctx.data.str_val = nla_data(opt_data_attr); + break; + case TEAM_OPTION_TYPE_BINARY: +- tbinary.data_len = data_len; +- tbinary.data = nla_data(opt_data_attr); +- arg = (long) &tbinary; ++ ctx.data.bin_val.len = data_len; ++ ctx.data.bin_val.ptr = nla_data(opt_data_attr); + break; + default: + BUG(); + } +- err = team_option_set(team, option, &arg); ++ err = team_option_set(team, opt_inst, &ctx); + if (err) + goto team_put; + } +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +index f4d960e..6cde1ab 100644 +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -59,23 +59,21 @@ static void ab_port_leave(struct team *team, struct team_port *port) + RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); + } + +-static int ab_active_port_get(struct team *team, void *arg) ++static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) + { +- u32 *ifindex = arg; +- +- *ifindex = 0; + if (ab_priv(team)->active_port) +- *ifindex = ab_priv(team)->active_port->dev->ifindex; ++ ctx->data.u32_val = ab_priv(team)->active_port->dev->ifindex; ++ else ++ ctx->data.u32_val = 0; + return 0; + } + +-static int ab_active_port_set(struct team *team, void *arg) ++static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx) + { +- u32 *ifindex = arg; + struct team_port *port; + + list_for_each_entry_rcu(port, &team->port_list, list) { +- if (port->dev->ifindex == *ifindex) { ++ if (port->dev->ifindex == ctx->data.u32_val) { + rcu_assign_pointer(ab_priv(team)->active_port, port); + return 0; + } +diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c +index ed20f39..167cdb4 100644 +--- a/drivers/net/team/team_mode_loadbalance.c ++++ b/drivers/net/team/team_mode_loadbalance.c +@@ -52,22 +52,21 @@ drop: + return false; + } + +-static int lb_bpf_func_get(struct team *team, void *arg) ++static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) + { +- struct team_option_binary *tbinary = team_optarg_tbinary(arg); +- +- memset(tbinary, 0, sizeof(*tbinary)); +- if (!lb_priv(team)->orig_fprog) ++ if (!lb_priv(team)->orig_fprog) { ++ ctx->data.bin_val.len = 0; ++ ctx->data.bin_val.ptr = NULL; + return 0; +- +- tbinary->data_len = lb_priv(team)->orig_fprog->len * +- sizeof(struct sock_filter); +- tbinary->data = lb_priv(team)->orig_fprog->filter; ++ } ++ ctx->data.bin_val.len = lb_priv(team)->orig_fprog->len * ++ sizeof(struct sock_filter); ++ ctx->data.bin_val.ptr = lb_priv(team)->orig_fprog->filter; + return 0; + } + + static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, +- void *data) ++ const void *data) + { + struct sock_fprog *fprog; + struct sock_filter *filter = (struct sock_filter *) data; +@@ -93,16 +92,15 @@ static void __fprog_destroy(struct sock_fprog *fprog) + kfree(fprog); + } + +-static int lb_bpf_func_set(struct team *team, void *arg) ++static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) + { +- struct team_option_binary *tbinary = team_optarg_tbinary(arg); + struct sk_filter *fp = NULL; + struct sock_fprog *fprog = NULL; + int err; + +- if (tbinary->data_len) { +- err = __fprog_create(&fprog, tbinary->data_len, +- tbinary->data); ++ if (ctx->data.bin_val.len) { ++ err = __fprog_create(&fprog, ctx->data.bin_val.len, ++ ctx->data.bin_val.ptr); + if (err) + return err; + err = sk_unattached_filter_create(&fp, fprog); +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 41163ac..6f27c84 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -71,25 +71,27 @@ enum team_option_type { + TEAM_OPTION_TYPE_BINARY, + }; + ++struct team_gsetter_ctx { ++ union { ++ u32 u32_val; ++ const char *str_val; ++ struct { ++ const void *ptr; ++ u32 len; ++ } bin_val; ++ } data; ++ struct team_port *port; ++}; ++ + struct team_option { + struct list_head list; + const char *name; ++ bool per_port; + enum team_option_type type; +- int (*getter)(struct team *team, void *arg); +- int (*setter)(struct team *team, void *arg); +- +- /* Custom gennetlink interface related flags */ +- bool changed; +- bool removed; ++ int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); ++ int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); + }; + +-struct team_option_binary { +- u32 data_len; +- void *data; +-}; +- +-#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg)) +- + struct team_mode { + struct list_head list; + const char *kind; +@@ -118,6 +120,7 @@ struct team { + struct list_head port_list; + + struct list_head option_list; ++ struct list_head option_inst_list; /* list of option instances */ + + const struct team_mode *mode; + struct team_mode_ops ops; +@@ -224,6 +227,7 @@ enum { + TEAM_ATTR_OPTION_TYPE, /* u8 */ + TEAM_ATTR_OPTION_DATA, /* dynamic */ + TEAM_ATTR_OPTION_REMOVED, /* flag */ ++ TEAM_ATTR_OPTION_PORT_IFINDEX, /* u32 */ /* for per-port options */ + + __TEAM_ATTR_OPTION_MAX, + TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, diff --git a/debian/patches/features/all/team/0017-team-add-bool-option-type.patch b/debian/patches/features/all/team/0017-team-add-bool-option-type.patch new file mode 100644 index 000000000..077e46621 --- /dev/null +++ b/debian/patches/features/all/team/0017-team-add-bool-option-type.patch @@ -0,0 +1,137 @@ +From: Jiri Pirko +Date: Tue, 10 Apr 2012 05:15:43 +0000 +Subject: [17/23] team: add bool option type + +commit 14f066bab19946545130a7379f420af860a02ae8 upstream. + +Add another (hopefully last) option type. Use NLA_FLAG to implement +that. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 40 +++++++++++++++++++++++++++++----------- + include/linux/if_team.h | 2 ++ + 2 files changed, 31 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index eaf8441..2645fae 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1463,6 +1463,16 @@ static int team_nl_fill_options_get(struct sk_buff *skb, + ctx.data.bin_val.len, ctx.data.bin_val.ptr)) + goto nla_put_failure; + break; ++ case TEAM_OPTION_TYPE_BOOL: ++ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_FLAG)) ++ goto nla_put_failure; ++ err = team_option_get(team, opt_inst, &ctx); ++ if (err) ++ goto errout; ++ if (ctx.data.bool_val && ++ nla_put_flag(skb, TEAM_ATTR_OPTION_DATA)) ++ goto nla_put_failure; ++ break; + default: + BUG(); + } +@@ -1524,6 +1534,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { + struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; + struct nlattr *attr_port_ifindex; ++ struct nlattr *attr_data; + enum team_option_type opt_type; + int opt_port_ifindex = 0; /* != 0 for per-port options */ + struct team_option_inst *opt_inst; +@@ -1539,8 +1550,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + if (err) + goto team_put; + if (!opt_attrs[TEAM_ATTR_OPTION_NAME] || +- !opt_attrs[TEAM_ATTR_OPTION_TYPE] || +- !opt_attrs[TEAM_ATTR_OPTION_DATA]) { ++ !opt_attrs[TEAM_ATTR_OPTION_TYPE]) { + err = -EINVAL; + goto team_put; + } +@@ -1554,10 +1564,19 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + case NLA_BINARY: + opt_type = TEAM_OPTION_TYPE_BINARY; + break; ++ case NLA_FLAG: ++ opt_type = TEAM_OPTION_TYPE_BOOL; ++ break; + default: + goto team_put; + } + ++ attr_data = opt_attrs[TEAM_ATTR_OPTION_DATA]; ++ if (opt_type != TEAM_OPTION_TYPE_BOOL && !attr_data) { ++ err = -EINVAL; ++ goto team_put; ++ } ++ + opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]); + attr_port_ifindex = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX]; + if (attr_port_ifindex) +@@ -1565,9 +1584,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + + list_for_each_entry(opt_inst, &team->option_inst_list, list) { + struct team_option *option = opt_inst->option; +- struct nlattr *opt_data_attr; + struct team_gsetter_ctx ctx; +- int data_len; + int tmp_ifindex; + + tmp_ifindex = opt_inst->port ? +@@ -1577,23 +1594,24 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) + tmp_ifindex != opt_port_ifindex) + continue; + opt_found = true; +- opt_data_attr = opt_attrs[TEAM_ATTR_OPTION_DATA]; +- data_len = nla_len(opt_data_attr); + ctx.port = opt_inst->port; + switch (opt_type) { + case TEAM_OPTION_TYPE_U32: +- ctx.data.u32_val = nla_get_u32(opt_data_attr); ++ ctx.data.u32_val = nla_get_u32(attr_data); + break; + case TEAM_OPTION_TYPE_STRING: +- if (data_len > TEAM_STRING_MAX_LEN) { ++ if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) { + err = -EINVAL; + goto team_put; + } +- ctx.data.str_val = nla_data(opt_data_attr); ++ ctx.data.str_val = nla_data(attr_data); + break; + case TEAM_OPTION_TYPE_BINARY: +- ctx.data.bin_val.len = data_len; +- ctx.data.bin_val.ptr = nla_data(opt_data_attr); ++ ctx.data.bin_val.len = nla_len(attr_data); ++ ctx.data.bin_val.ptr = nla_data(attr_data); ++ break; ++ case TEAM_OPTION_TYPE_BOOL: ++ ctx.data.bool_val = attr_data ? true : false; + break; + default: + BUG(); +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 6f27c84..78c84fd 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -69,6 +69,7 @@ enum team_option_type { + TEAM_OPTION_TYPE_U32, + TEAM_OPTION_TYPE_STRING, + TEAM_OPTION_TYPE_BINARY, ++ TEAM_OPTION_TYPE_BOOL, + }; + + struct team_gsetter_ctx { +@@ -79,6 +80,7 @@ struct team_gsetter_ctx { + const void *ptr; + u32 len; + } bin_val; ++ bool bool_val; + } data; + struct team_port *port; + }; diff --git a/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch b/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch new file mode 100644 index 000000000..1dadd07c6 --- /dev/null +++ b/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch @@ -0,0 +1,184 @@ +From: Jiri Pirko +Date: Tue, 10 Apr 2012 05:15:44 +0000 +Subject: [18/23] team: add user_linkup and user_linkup_enabled per-port + option + +commit 71472ec12c61dd305ab4d11822af7ecc4f9717f9 upstream. + +Allows userspace to setup linkup for ports. Default is to take linkup +directly from ethtool state. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 72 +++++++++++++++++++++++++++++++++++++++++------ + include/linux/if_team.h | 26 +++++++++++------ + 2 files changed, 81 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 2645fae..e639abe 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -76,6 +76,11 @@ int team_port_set_team_mac(struct team_port *port) + } + EXPORT_SYMBOL(team_port_set_team_mac); + ++static void team_refresh_port_linkup(struct team_port *port) ++{ ++ port->linkup = port->user.linkup_enabled ? port->user.linkup : ++ port->state.linkup; ++} + + /******************* + * Options handling +@@ -880,6 +885,40 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) + return team_change_mode(team, ctx->data.str_val); + } + ++static int team_user_linkup_option_get(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ ctx->data.bool_val = ctx->port->user.linkup; ++ return 0; ++} ++ ++static int team_user_linkup_option_set(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ ctx->port->user.linkup = ctx->data.bool_val; ++ team_refresh_port_linkup(ctx->port); ++ return 0; ++} ++ ++static int team_user_linkup_en_option_get(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ struct team_port *port = ctx->port; ++ ++ ctx->data.bool_val = port->user.linkup_enabled; ++ return 0; ++} ++ ++static int team_user_linkup_en_option_set(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ struct team_port *port = ctx->port; ++ ++ port->user.linkup_enabled = ctx->data.bool_val; ++ team_refresh_port_linkup(ctx->port); ++ return 0; ++} ++ + static const struct team_option team_options[] = { + { + .name = "mode", +@@ -887,6 +926,20 @@ static const struct team_option team_options[] = { + .getter = team_mode_option_get, + .setter = team_mode_option_set, + }, ++ { ++ .name = "user_linkup", ++ .type = TEAM_OPTION_TYPE_BOOL, ++ .per_port = true, ++ .getter = team_user_linkup_option_get, ++ .setter = team_user_linkup_option_set, ++ }, ++ { ++ .name = "user_linkup_enabled", ++ .type = TEAM_OPTION_TYPE_BOOL, ++ .per_port = true, ++ .getter = team_user_linkup_en_option_get, ++ .setter = team_user_linkup_en_option_set, ++ }, + }; + + static int team_init(struct net_device *dev) +@@ -1670,10 +1723,10 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, + } + if ((port->removed && + nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || +- (port->linkup && ++ (port->state.linkup && + nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || +- nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->speed) || +- nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex)) ++ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || ++ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) + goto nla_put_failure; + nla_nest_end(skb, port_item); + } +@@ -1833,23 +1886,24 @@ static void __team_port_change_check(struct team_port *port, bool linkup) + { + int err; + +- if (!port->removed && port->linkup == linkup) ++ if (!port->removed && port->state.linkup == linkup) + return; + + port->changed = true; +- port->linkup = linkup; ++ port->state.linkup = linkup; ++ team_refresh_port_linkup(port); + if (linkup) { + struct ethtool_cmd ecmd; + + err = __ethtool_get_settings(port->dev, &ecmd); + if (!err) { +- port->speed = ethtool_cmd_speed(&ecmd); +- port->duplex = ecmd.duplex; ++ port->state.speed = ethtool_cmd_speed(&ecmd); ++ port->state.duplex = ecmd.duplex; + goto send_event; + } + } +- port->speed = 0; +- port->duplex = 0; ++ port->state.speed = 0; ++ port->state.duplex = 0; + + send_event: + err = team_nl_send_event_port_list_get(port->team); +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 78c84fd..5fd5ab1 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -33,6 +33,24 @@ struct team_port { + struct team *team; + int index; + ++ bool linkup; /* either state.linkup or user.linkup */ ++ ++ struct { ++ bool linkup; ++ u32 speed; ++ u8 duplex; ++ } state; ++ ++ /* Values set by userspace */ ++ struct { ++ bool linkup; ++ bool linkup_enabled; ++ } user; ++ ++ /* Custom gennetlink interface related flags */ ++ bool changed; ++ bool removed; ++ + /* + * A place for storing original values of the device before it + * become a port. +@@ -42,14 +60,6 @@ struct team_port { + unsigned int mtu; + } orig; + +- bool linkup; +- u32 speed; +- u8 duplex; +- +- /* Custom gennetlink interface related flags */ +- bool changed; +- bool removed; +- + struct rcu_head rcu; + }; + diff --git a/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch b/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch new file mode 100644 index 000000000..13fde09c1 --- /dev/null +++ b/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch @@ -0,0 +1,27 @@ +From: Jiri Pirko +Date: Tue, 10 Apr 2012 05:15:45 +0000 +Subject: [19/23] team: ab: walk through port list non-rcu + +commit 679b16073008cc536e85e2773e67234b596fb62e upstream. + +Since team->lock is being held, _rcu variant make no sense. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team_mode_activebackup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +index 6cde1ab..a715c40 100644 +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -72,7 +72,7 @@ static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx) + { + struct team_port *port; + +- list_for_each_entry_rcu(port, &team->port_list, list) { ++ list_for_each_entry(port, &team->port_list, list) { + if (port->dev->ifindex == ctx->data.u32_val) { + rcu_assign_pointer(ab_priv(team)->active_port, port); + return 0; diff --git a/debian/patches/features/all/team/0020-team-add-missed-statics.patch b/debian/patches/features/all/team/0020-team-add-missed-statics.patch new file mode 100644 index 000000000..da5f23a29 --- /dev/null +++ b/debian/patches/features/all/team/0020-team-add-missed-statics.patch @@ -0,0 +1,66 @@ +From: Jiri Pirko +Date: Tue, 10 Apr 2012 05:15:46 +0000 +Subject: [20/23] team: add missed "statics" + +commit cade455596504fae8e134a27189713ddf7c6d04d upstream. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 2 +- + drivers/net/team/team_mode_activebackup.c | 4 ++-- + drivers/net/team/team_mode_loadbalance.c | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index e639abe..153a62d 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -65,7 +65,7 @@ static int __set_port_mac(struct net_device *port_dev, + return dev_set_mac_address(port_dev, &addr); + } + +-int team_port_set_orig_mac(struct team_port *port) ++static int team_port_set_orig_mac(struct team_port *port) + { + return __set_port_mac(port->dev, port->orig.dev_addr); + } +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +index a715c40..fd6bd03 100644 +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -90,12 +90,12 @@ static const struct team_option ab_options[] = { + }, + }; + +-int ab_init(struct team *team) ++static int ab_init(struct team *team) + { + return team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); + } + +-void ab_exit(struct team *team) ++static void ab_exit(struct team *team) + { + team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options)); + } +diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c +index 167cdb4..2b506b2 100644 +--- a/drivers/net/team/team_mode_loadbalance.c ++++ b/drivers/net/team/team_mode_loadbalance.c +@@ -130,13 +130,13 @@ static const struct team_option lb_options[] = { + }, + }; + +-int lb_init(struct team *team) ++static int lb_init(struct team *team) + { + return team_options_register(team, lb_options, + ARRAY_SIZE(lb_options)); + } + +-void lb_exit(struct team *team) ++static void lb_exit(struct team *team) + { + team_options_unregister(team, lb_options, + ARRAY_SIZE(lb_options)); diff --git a/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch b/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch new file mode 100644 index 000000000..e90a68c34 --- /dev/null +++ b/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch @@ -0,0 +1,41 @@ +From: Jiri Pirko +Date: Fri, 20 Apr 2012 04:42:04 +0000 +Subject: [21/23] team: lb: let userspace care about port macs + +commit 4c78bb845bd2aaf1f7136e75314c7d034cfd120f upstream. + +Better to leave this for userspace + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team_mode_loadbalance.c | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c +index 2b506b2..438d5b8 100644 +--- a/drivers/net/team/team_mode_loadbalance.c ++++ b/drivers/net/team/team_mode_loadbalance.c +@@ -142,22 +142,10 @@ static void lb_exit(struct team *team) + ARRAY_SIZE(lb_options)); + } + +-static int lb_port_enter(struct team *team, struct team_port *port) +-{ +- return team_port_set_team_mac(port); +-} +- +-static void lb_port_change_mac(struct team *team, struct team_port *port) +-{ +- team_port_set_team_mac(port); +-} +- + static const struct team_mode_ops lb_mode_ops = { + .init = lb_init, + .exit = lb_exit, + .transmit = lb_transmit, +- .port_enter = lb_port_enter, +- .port_change_mac = lb_port_change_mac, + }; + + static struct team_mode lb_mode = { diff --git a/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch b/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch new file mode 100644 index 000000000..8df50f7d6 --- /dev/null +++ b/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch @@ -0,0 +1,212 @@ +From: Jiri Pirko +Date: Fri, 20 Apr 2012 04:42:05 +0000 +Subject: [22/23] team: allow to enable/disable ports + +commit 19a0b58e506b06fd41659d8734bba6a3e87980f4 upstream. + +This patch changes content of hashlist (used to get port struct by +computed index (0...en_port_count-1)). Now the hash list contains only +enabled ports so userspace will be able to say what ports can be used +for tx/rx. This becomes handy when userspace will need to disable ports +which does not belong to active aggregator. By default, newly added port +is enabled. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 51 ++++++++++++++++++++---------- + drivers/net/team/team_mode_loadbalance.c | 2 +- + drivers/net/team/team_mode_roundrobin.c | 2 +- + include/linux/if_team.h | 15 +++++---- + 4 files changed, 45 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 153a62d..fe7ca40 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -559,6 +559,8 @@ static int team_change_mode(struct team *team, const char *kind) + * Rx path frame handler + ************************/ + ++static bool team_port_enabled(struct team_port *port); ++ + /* note: already called with rcu_read_lock */ + static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) + { +@@ -575,8 +577,12 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) + + port = team_port_get_rcu(skb->dev); + team = port->team; +- +- res = team->ops.receive(team, port, skb); ++ if (!team_port_enabled(port)) { ++ /* allow exact match delivery for disabled ports */ ++ res = RX_HANDLER_EXACT; ++ } else { ++ res = team->ops.receive(team, port, skb); ++ } + if (res == RX_HANDLER_ANOTHER) { + struct team_pcpu_stats *pcpu_stats; + +@@ -612,17 +618,25 @@ static bool team_port_find(const struct team *team, + return false; + } + ++static bool team_port_enabled(struct team_port *port) ++{ ++ return port->index != -1; ++} ++ + /* +- * Add/delete port to the team port list. Write guarded by rtnl_lock. +- * Takes care of correct port->index setup (might be racy). ++ * Enable/disable port by adding to enabled port hashlist and setting ++ * port->index (Might be racy so reader could see incorrect ifindex when ++ * processing a flying packet, but that is not a problem). Write guarded ++ * by team->lock. + */ +-static void team_port_list_add_port(struct team *team, +- struct team_port *port) ++static void team_port_enable(struct team *team, ++ struct team_port *port) + { +- port->index = team->port_count++; ++ if (team_port_enabled(port)) ++ return; ++ port->index = team->en_port_count++; + hlist_add_head_rcu(&port->hlist, + team_port_index_hash(team, port->index)); +- list_add_tail_rcu(&port->list, &team->port_list); + } + + static void __reconstruct_port_hlist(struct team *team, int rm_index) +@@ -630,7 +644,7 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index) + int i; + struct team_port *port; + +- for (i = rm_index + 1; i < team->port_count; i++) { ++ for (i = rm_index + 1; i < team->en_port_count; i++) { + port = team_get_port_by_index(team, i); + hlist_del_rcu(&port->hlist); + port->index--; +@@ -639,15 +653,17 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index) + } + } + +-static void team_port_list_del_port(struct team *team, +- struct team_port *port) ++static void team_port_disable(struct team *team, ++ struct team_port *port) + { + int rm_index = port->index; + ++ if (!team_port_enabled(port)) ++ return; + hlist_del_rcu(&port->hlist); +- list_del_rcu(&port->list); + __reconstruct_port_hlist(team, rm_index); +- team->port_count--; ++ team->en_port_count--; ++ port->index = -1; + } + + #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ +@@ -800,7 +816,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + goto err_option_port_add; + } + +- team_port_list_add_port(team, port); ++ port->index = -1; ++ team_port_enable(team, port); ++ list_add_tail_rcu(&port->list, &team->port_list); + team_adjust_ops(team); + __team_compute_features(team); + __team_port_change_check(port, !!netif_carrier_ok(port_dev)); +@@ -849,7 +867,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + + port->removed = true; + __team_port_change_check(port, false); +- team_port_list_del_port(team, port); ++ team_port_disable(team, port); ++ list_del_rcu(&port->list); + team_adjust_ops(team); + team_option_port_del(team, port); + netdev_rx_handler_unregister(port_dev); +@@ -956,7 +975,7 @@ static int team_init(struct net_device *dev) + return -ENOMEM; + + for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) +- INIT_HLIST_HEAD(&team->port_hlist[i]); ++ INIT_HLIST_HEAD(&team->en_port_hlist[i]); + INIT_LIST_HEAD(&team->port_list); + + team_adjust_ops(team); +diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c +index 438d5b8..86e8183 100644 +--- a/drivers/net/team/team_mode_loadbalance.c ++++ b/drivers/net/team/team_mode_loadbalance.c +@@ -38,7 +38,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) + if (unlikely(!fp)) + goto drop; + hash = SK_RUN_FILTER(fp, skb); +- port_index = hash % team->port_count; ++ port_index = hash % team->en_port_count; + port = team_get_port_by_index_rcu(team, port_index); + if (unlikely(!port)) + goto drop; +diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c +index a0e8f80..6abfbdc 100644 +--- a/drivers/net/team/team_mode_roundrobin.c ++++ b/drivers/net/team/team_mode_roundrobin.c +@@ -50,7 +50,7 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) + struct team_port *port; + int port_index; + +- port_index = rr_priv(team)->sent_packets++ % team->port_count; ++ port_index = rr_priv(team)->sent_packets++ % team->en_port_count; + port = team_get_port_by_index_rcu(team, port_index); + port = __get_first_port_up(team, port); + if (unlikely(!port)) +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 5fd5ab1..8185f57 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -28,10 +28,10 @@ struct team; + + struct team_port { + struct net_device *dev; +- struct hlist_node hlist; /* node in hash list */ ++ struct hlist_node hlist; /* node in enabled ports hash list */ + struct list_head list; /* node in ordinary list */ + struct team *team; +- int index; ++ int index; /* index of enabled port. If disabled, it's set to -1 */ + + bool linkup; /* either state.linkup or user.linkup */ + +@@ -125,11 +125,12 @@ struct team { + struct mutex lock; /* used for overall locking, e.g. port lists write */ + + /* +- * port lists with port count ++ * List of enabled ports and their count + */ +- int port_count; +- struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES]; +- struct list_head port_list; ++ int en_port_count; ++ struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; ++ ++ struct list_head port_list; /* list of all ports */ + + struct list_head option_list; + struct list_head option_inst_list; /* list of option instances */ +@@ -142,7 +143,7 @@ struct team { + static inline struct hlist_head *team_port_index_hash(struct team *team, + int port_index) + { +- return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; ++ return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; + } + + static inline struct team_port *team_get_port_by_index(struct team *team, diff --git a/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch b/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch new file mode 100644 index 000000000..09ef3e098 --- /dev/null +++ b/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch @@ -0,0 +1,54 @@ +From: Jiri Pirko +Date: Fri, 20 Apr 2012 04:42:06 +0000 +Subject: [23/23] team: add per-port option for enabling/disabling ports + +commit acd69962341a956b5bcc5b4178b70fa527d7ce11 upstream. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + drivers/net/team/team.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index fe7ca40..c61ae35 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -904,6 +904,23 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) + return team_change_mode(team, ctx->data.str_val); + } + ++static int team_port_en_option_get(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ ctx->data.bool_val = team_port_enabled(ctx->port); ++ return 0; ++} ++ ++static int team_port_en_option_set(struct team *team, ++ struct team_gsetter_ctx *ctx) ++{ ++ if (ctx->data.bool_val) ++ team_port_enable(team, ctx->port); ++ else ++ team_port_disable(team, ctx->port); ++ return 0; ++} ++ + static int team_user_linkup_option_get(struct team *team, + struct team_gsetter_ctx *ctx) + { +@@ -946,6 +963,13 @@ static const struct team_option team_options[] = { + .setter = team_mode_option_set, + }, + { ++ .name = "enabled", ++ .type = TEAM_OPTION_TYPE_BOOL, ++ .per_port = true, ++ .getter = team_port_en_option_get, ++ .setter = team_port_en_option_set, ++ }, ++ { + .name = "user_linkup", + .type = TEAM_OPTION_TYPE_BOOL, + .per_port = true, diff --git a/debian/patches/series-all b/debian/patches/series-all index a57a4d24c..658496c17 100644 --- a/debian/patches/series-all +++ b/debian/patches/series-all @@ -309,3 +309,31 @@ bugfix/all/mm-fix-vma_resv_map-null-pointer.patch bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch bugfix/all/fix-scsi_wait_scan.patch + +features/all/define-netdev_features_t.patch +features/all/filter-Allow-to-create-sk-unattached-filters.patch + +# team driver from 3.5ish +features/all/team/0001-net-introduce-ethernet-teaming-device.patch +features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch +features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch +features/all/team/0004-team-replicate-options-on-register.patch +features/all/team/0005-team-add-fix_features.patch +features/all/team/0006-team-avoid-using-variable-length-array.patch +features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch +features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch +features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch +features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch +features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch +features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch +features/all/team/0013-team-Stop-using-NLA_PUT.patch +features/all/team/0014-team-add-binary-option-type.patch +features/all/team/0015-team-add-loadbalance-mode.patch +features/all/team/0016-team-add-support-for-per-port-options.patch +features/all/team/0017-team-add-bool-option-type.patch +features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch +features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch +features/all/team/0020-team-add-missed-statics.patch +features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch +features/all/team/0022-team-allow-to-enable-disable-ports.patch +features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch From de6102258b6fc4b111129c4659f703e5ec64bcd2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 7 Jun 2012 06:59:12 +0000 Subject: [PATCH 11/30] proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) svn path=/dists/sid/linux/; revision=19095 --- debian/changelog | 1 + .../0001-procfs-parse-mount-options.patch | 167 +++++++++ ...fs-add-hidepid-and-gid-mount-options.patch | 332 ++++++++++++++++++ ...pointer-deref-in-proc_pid_permission.patch | 42 +++ .../0004-proc-fix-mount-t-proc-o-AAA.patch | 49 +++ debian/patches/series-all | 6 + 6 files changed, 597 insertions(+) create mode 100644 debian/patches/features/all/hidepid/0001-procfs-parse-mount-options.patch create mode 100644 debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch create mode 100644 debian/patches/features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch create mode 100644 debian/patches/features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch diff --git a/debian/changelog b/debian/changelog index 003832033..4fbdca55b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -21,6 +21,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low modules as required even if they are built-in in some configurations * filter: Allow to create sk-unattached filters * net: Backport team driver from Linux 3.5-rc1 + * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/patches/features/all/hidepid/0001-procfs-parse-mount-options.patch b/debian/patches/features/all/hidepid/0001-procfs-parse-mount-options.patch new file mode 100644 index 000000000..8eabaebd7 --- /dev/null +++ b/debian/patches/features/all/hidepid/0001-procfs-parse-mount-options.patch @@ -0,0 +1,167 @@ +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:27 -0800 +Subject: procfs: parse mount options + +commit 97412950b10e64f347aec4a9b759395c2465adf6 upstream. + +Add support for procfs mount options. Actual mount options are coming in +the next patches. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: super_operations::show_options takes a + struct vfsmount *, not struct dentry *] +--- + fs/proc/inode.c | 10 ++++++++++ + fs/proc/internal.h | 1 + + fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 64 insertions(+), 2 deletions(-) + +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -17,7 +18,9 @@ + #include + #include + #include ++#include + #include ++#include + + #include + #include +@@ -102,12 +105,19 @@ + init_once); + } + ++static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) ++{ ++ return 0; ++} ++ + static const struct super_operations proc_sops = { + .alloc_inode = proc_alloc_inode, + .destroy_inode = proc_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = proc_evict_inode, + .statfs = simple_statfs, ++ .remount_fs = proc_remount, ++ .show_options = proc_show_options, + }; + + static void __pde_users_dec(struct proc_dir_entry *pde) +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -117,6 +117,7 @@ + + int proc_fill_super(struct super_block *); + struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); ++int proc_remount(struct super_block *sb, int *flags, char *data); + + /* + * These are generic /proc routines that use the internal +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +@@ -36,6 +37,48 @@ + return err; + } + ++enum { ++ Opt_err, ++}; ++ ++static const match_table_t tokens = { ++ {Opt_err, NULL}, ++}; ++ ++static int proc_parse_options(char *options, struct pid_namespace *pid) ++{ ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ pr_debug("proc: options = %s\n", options); ++ ++ if (!options) ++ return 1; ++ ++ while ((p = strsep(&options, ",")) != NULL) { ++ int token; ++ if (!*p) ++ continue; ++ ++ args[0].to = args[0].from = 0; ++ token = match_token(p, tokens, args); ++ switch (token) { ++ default: ++ pr_err("proc: unrecognized mount option \"%s\" " ++ "or missing value\n", p); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++int proc_remount(struct super_block *sb, int *flags, char *data) ++{ ++ struct pid_namespace *pid = sb->s_fs_info; ++ return !proc_parse_options(data, pid); ++} ++ + static struct dentry *proc_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -43,11 +86,15 @@ + struct super_block *sb; + struct pid_namespace *ns; + struct proc_inode *ei; ++ char *options; + +- if (flags & MS_KERNMOUNT) ++ if (flags & MS_KERNMOUNT) { + ns = (struct pid_namespace *)data; +- else ++ options = NULL; ++ } else { + ns = current->nsproxy->pid_ns; ++ options = data; ++ } + + sb = sget(fs_type, proc_test_super, proc_set_super, ns); + if (IS_ERR(sb)) +@@ -55,6 +102,10 @@ + + if (!sb->s_root) { + sb->s_flags = flags; ++ if (!proc_parse_options(options, ns)) { ++ deactivate_locked_super(sb); ++ return ERR_PTR(-EINVAL); ++ } + err = proc_fill_super(sb); + if (err) { + deactivate_locked_super(sb); diff --git a/debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch b/debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch new file mode 100644 index 000000000..f1adaf8dc --- /dev/null +++ b/debian/patches/features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch @@ -0,0 +1,332 @@ +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:31 -0800 +Subject: procfs: add hidepid= and gid= mount options + +commit 0499680a42141d86417a8fbaa8c8db806bea1201 upstream. + +Add support for mount options to restrict access to /proc/PID/ +directories. The default backward-compatible "relaxed" behaviour is left +untouched. + +The first mount option is called "hidepid" and its value defines how much +info about processes we want to be available for non-owners: + +hidepid=0 (default) means the old behavior - anybody may read all +world-readable /proc/PID/* files. + +hidepid=1 means users may not access any /proc// directories, but +their own. Sensitive files like cmdline, sched*, status are now protected +against other users. As permission checking done in proc_pid_permission() +and files' permissions are left untouched, programs expecting specific +files' modes are not confused. + +hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other +users. It doesn't mean that it hides whether a process exists (it can be +learned by other means, e.g. by kill -0 $PID), but it hides process' euid +and egid. It compicates intruder's task of gathering info about running +processes, whether some daemon runs with elevated privileges, whether +another user runs some sensitive program, whether other users run any +program at all, etc. + +gid=XXX defines a group that will be able to gather all processes' info +(as in hidepid=0 mode). This group should be used instead of putting +nonroot user in sudoers file or something. However, untrusted users (like +daemons, etc.) which are not supposed to monitor the tasks in the whole +system should not be added to the group. + +hidepid=1 or higher is designed to restrict access to procfs files, which +might reveal some sensitive private information like precise keystrokes +timings: + +http://www.openwall.com/lists/oss-security/2011/11/05/3 + +hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and +conky gracefully handle EPERM/ENOENT and behave as if the current user is +the only user running processes. pstree shows the process subtree which +contains "pstree" process. + +Note: the patch doesn't deal with setuid/setgid issues of keeping +preopened descriptors of procfs files (like +https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked +information like the scheduling counters of setuid apps doesn't threaten +anybody's privacy - only the user started the setuid program may read the +counters. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: super_operations::show_options takes a + struct vfsmount *, not struct dentry *] +--- + Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++ + fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++- + fs/proc/inode.c | 8 +++++ + fs/proc/root.c | 21 +++++++++-- + include/linux/pid_namespace.h | 2 ++ + 5 files changed, 135 insertions(+), 4 deletions(-) + +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -41,6 +41,8 @@ + 3.5 /proc//mountinfo - Information about mounts + 3.6 /proc//comm & /proc//task//comm + ++ 4 Configuring procfs ++ 4.1 Mount options + + ------------------------------------------------------------------------------ + Preface +@@ -1542,3 +1544,40 @@ + is limited in size compared to the cmdline value, so writing anything longer + then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated + comm value. ++ ++ ++------------------------------------------------------------------------------ ++Configuring procfs ++------------------------------------------------------------------------------ ++ ++4.1 Mount options ++--------------------- ++ ++The following mount options are supported: ++ ++ hidepid= Set /proc// access mode. ++ gid= Set the group authorized to learn processes information. ++ ++hidepid=0 means classic mode - everybody may access all /proc// directories ++(default). ++ ++hidepid=1 means users may not access any /proc// directories but their ++own. Sensitive files like cmdline, sched*, status are now protected against ++other users. This makes it impossible to learn whether any user runs ++specific program (given the program doesn't reveal itself by its behaviour). ++As an additional bonus, as /proc//cmdline is unaccessible for other users, ++poorly written programs passing sensitive information via program arguments are ++now protected against local eavesdroppers. ++ ++hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other ++users. It doesn't mean that it hides a fact whether a process with a specific ++pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), ++but it hides process' uid and gid, which may be learned by stat()'ing ++/proc// otherwise. It greatly complicates an intruder's task of gathering ++information about running processes, whether some daemon runs with elevated ++privileges, whether other user runs some sensitive program, whether other users ++run any program at all, etc. ++ ++gid= defines a group authorized to learn processes information otherwise ++prohibited by hidepid=. If you use some daemon like identd which needs to learn ++information about processes information, just add identd to this group. +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -574,6 +574,50 @@ + return 0; + } + ++/* ++ * May current process learn task's sched/cmdline info (for hide_pid_min=1) ++ * or euid/egid (for hide_pid_min=2)? ++ */ ++static bool has_pid_permissions(struct pid_namespace *pid, ++ struct task_struct *task, ++ int hide_pid_min) ++{ ++ if (pid->hide_pid < hide_pid_min) ++ return true; ++ if (in_group_p(pid->pid_gid)) ++ return true; ++ return ptrace_may_access(task, PTRACE_MODE_READ); ++} ++ ++ ++static int proc_pid_permission(struct inode *inode, int mask) ++{ ++ struct pid_namespace *pid = inode->i_sb->s_fs_info; ++ struct task_struct *task; ++ bool has_perms; ++ ++ task = get_proc_task(inode); ++ has_perms = has_pid_permissions(pid, task, 1); ++ put_task_struct(task); ++ ++ if (!has_perms) { ++ if (pid->hide_pid == 2) { ++ /* ++ * Let's make getdents(), stat(), and open() ++ * consistent with each other. If a process ++ * may not stat() a file, it shouldn't be seen ++ * in procfs at all. ++ */ ++ return -ENOENT; ++ } ++ ++ return -EPERM; ++ } ++ return generic_permission(inode, mask); ++} ++ ++ ++ + static const struct inode_operations proc_def_inode_operations = { + .setattr = proc_setattr, + }; +@@ -1642,6 +1686,7 @@ + struct inode *inode = dentry->d_inode; + struct task_struct *task; + const struct cred *cred; ++ struct pid_namespace *pid = dentry->d_sb->s_fs_info; + + generic_fillattr(inode, stat); + +@@ -1650,6 +1695,14 @@ + stat->gid = 0; + task = pid_task(proc_pid(inode), PIDTYPE_PID); + if (task) { ++ if (!has_pid_permissions(pid, task, 2)) { ++ rcu_read_unlock(); ++ /* ++ * This doesn't prevent learning whether PID exists, ++ * it only makes getattr() consistent with readdir(). ++ */ ++ return -ENOENT; ++ } + if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || + task_dumpable(task)) { + cred = __task_cred(task); +@@ -2794,6 +2847,7 @@ + .lookup = proc_tgid_base_lookup, + .getattr = pid_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) +@@ -2997,6 +3051,12 @@ + proc_pid_instantiate, iter.task, NULL); + } + ++static int fake_filldir(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned d_type) ++{ ++ return 0; ++} ++ + /* for the /proc/ directory itself, after non-process stuff has been done */ + int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + { +@@ -3004,6 +3064,7 @@ + struct task_struct *reaper; + struct tgid_iter iter; + struct pid_namespace *ns; ++ filldir_t __filldir; + + if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) + goto out_no_task; +@@ -3025,8 +3086,13 @@ + for (iter = next_tgid(ns, iter); + iter.task; + iter.tgid += 1, iter = next_tgid(ns, iter)) { ++ if (has_pid_permissions(ns, iter.task, 2)) ++ __filldir = filldir; ++ else ++ __filldir = fake_filldir; ++ + filp->f_pos = iter.tgid + TGID_OFFSET; +- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { ++ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { + put_task_struct(iter.task); + goto out; + } +@@ -3361,6 +3427,7 @@ + .lookup = proc_task_lookup, + .getattr = proc_task_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static const struct file_operations proc_task_operations = { +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -107,6 +107,14 @@ + + static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) + { ++ struct super_block *sb = vfs->mnt_sb; ++ struct pid_namespace *pid = sb->s_fs_info; ++ ++ if (pid->pid_gid) ++ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); ++ if (pid->hide_pid != 0) ++ seq_printf(seq, ",hidepid=%u", pid->hide_pid); ++ + return 0; + } + +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -38,10 +38,12 @@ + } + + enum { +- Opt_err, ++ Opt_gid, Opt_hidepid, Opt_err, + }; + + static const match_table_t tokens = { ++ {Opt_hidepid, "hidepid=%u"}, ++ {Opt_gid, "gid=%u"}, + {Opt_err, NULL}, + }; + +@@ -49,8 +51,7 @@ + { + char *p; + substring_t args[MAX_OPT_ARGS]; +- +- pr_debug("proc: options = %s\n", options); ++ int option; + + if (!options) + return 1; +@@ -63,6 +64,20 @@ + args[0].to = args[0].from = 0; + token = match_token(p, tokens, args); + switch (token) { ++ case Opt_gid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ pid->pid_gid = option; ++ break; ++ case Opt_hidepid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ if (option < 0 || option > 2) { ++ pr_err("proc: hidepid value must be between 0 and 2.\n"); ++ return 0; ++ } ++ pid->hide_pid = option; ++ break; + default: + pr_err("proc: unrecognized mount option \"%s\" " + "or missing value\n", p); +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,6 +30,8 @@ + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++ gid_t pid_gid; ++ int hide_pid; + }; + + extern struct pid_namespace init_pid_ns; diff --git a/debian/patches/features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch b/debian/patches/features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch new file mode 100644 index 000000000..6e4ecaa53 --- /dev/null +++ b/debian/patches/features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch @@ -0,0 +1,42 @@ +From: Xiaotian Feng +Date: Thu, 12 Jan 2012 17:17:08 -0800 +Subject: proc: fix null pointer deref in proc_pid_permission() + +commit a2ef990ab5a6705a356d146dd773a3b359787497 upstream. + +get_proc_task() can fail to search the task and return NULL, +put_task_struct() will then bomb the kernel with following oops: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] proc_pid_permission+0x64/0xe0 + PGD 112075067 PUD 112814067 PMD 0 + Oops: 0002 [#1] PREEMPT SMP + +This is a regression introduced by commit 0499680a ("procfs: add hidepid= +and gid= mount options"). The kernel should return -ESRCH if +get_proc_task() failed. + +Signed-off-by: Xiaotian Feng +Cc: Al Viro +Cc: Vasiliy Kulikov +Cc: Stephen Wilson +Acked-by: David Rientjes +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 8173dfd..5485a53 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask) + bool has_perms; + + task = get_proc_task(inode); ++ if (!task) ++ return -ESRCH; + has_perms = has_pid_permissions(pid, task, 1); + put_task_struct(task); + diff --git a/debian/patches/features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch b/debian/patches/features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch new file mode 100644 index 000000000..da1a2f4b2 --- /dev/null +++ b/debian/patches/features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch @@ -0,0 +1,49 @@ +From: Vasiliy Kulikov +Date: Thu, 5 Apr 2012 14:25:04 -0700 +Subject: proc: fix mount -t proc -o AAA + +commit 99663be772c827b8f5f594fe87eb4807be1994e5 upstream. + +The proc_parse_options() call from proc_mount() runs only once at boot +time. So on any later mount attempt, any mount options are ignored +because ->s_root is already initialized. + +As a consequence, "mount -o " will ignore the options. The +only way to change mount options is "mount -o remount,". + +To fix this, parse the mount options unconditionally. + +Signed-off-by: Vasiliy Kulikov +Reported-by: Arkadiusz Miskiewicz +Tested-by: Arkadiusz Miskiewicz +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Valdis Kletnieks +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/root.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 46a15d8..eed44bf 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -115,12 +115,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + if (IS_ERR(sb)) + return ERR_CAST(sb); + ++ if (!proc_parse_options(options, ns)) { ++ deactivate_locked_super(sb); ++ return ERR_PTR(-EINVAL); ++ } ++ + if (!sb->s_root) { + sb->s_flags = flags; +- if (!proc_parse_options(options, ns)) { +- deactivate_locked_super(sb); +- return ERR_PTR(-EINVAL); +- } + err = proc_fill_super(sb); + if (err) { + deactivate_locked_super(sb); diff --git a/debian/patches/series-all b/debian/patches/series-all index 658496c17..1448a6f5b 100644 --- a/debian/patches/series-all +++ b/debian/patches/series-all @@ -337,3 +337,9 @@ features/all/team/0020-team-add-missed-statics.patch features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch features/all/team/0022-team-allow-to-enable-disable-ports.patch features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch + +# procfs hidepid from 3.4 +features/all/hidepid/0001-procfs-parse-mount-options.patch +features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch +features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch +features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch From 1f51066386dfe2495d393dee9bbc6548aac8f846 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 7 Jun 2012 13:57:50 +0000 Subject: [PATCH 12/30] NFSv4: Reduce the footprint of the idmapper (Closes: #657078) svn path=/dists/sid/linux/; revision=19096 --- debian/changelog | 1 + ...reduce-the-footprint-of-the-idmapper.patch | 124 ++++++++++++++++++ ...Reduce-the-footprint-of-the-idmapper.patch | 62 +++++++++ debian/patches/series-all | 3 + 4 files changed, 190 insertions(+) create mode 100644 debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch create mode 100644 debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch diff --git a/debian/changelog b/debian/changelog index 4fbdca55b..231e435eb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * filter: Allow to create sk-unattached filters * net: Backport team driver from Linux 3.5-rc1 * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) + * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch b/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..7f1f81532 --- /dev/null +++ b/debian/patches/bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,124 @@ +From: Trond Myklebust +Date: Wed, 8 Feb 2012 13:39:15 -0500 +Subject: [2/2] NFSv4: Further reduce the footprint of the idmapper + +commit 685f50f9188ac1e8244d0340a9d6ea36b6136cec upstream. + +Don't allocate the legacy idmapper tables until we actually need +them. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +[bwh: Backported to 3.2: adjust context in nfs_idmap_delete()] +--- + fs/nfs/idmap.c | 42 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 36 insertions(+), 6 deletions(-) + +--- a/fs/nfs/idmap.c ++++ b/fs/nfs/idmap.c +@@ -323,7 +323,7 @@ + + struct idmap_hashtable { + __u8 h_type; +- struct idmap_hashent h_entries[IDMAP_HASH_SZ]; ++ struct idmap_hashent *h_entries; + }; + + struct idmap { +@@ -378,20 +378,39 @@ + return 0; + } + ++static void ++idmap_alloc_hashtable(struct idmap_hashtable *h) ++{ ++ if (h->h_entries != NULL) ++ return; ++ h->h_entries = kcalloc(IDMAP_HASH_SZ, ++ sizeof(*h->h_entries), ++ GFP_KERNEL); ++} ++ ++static void ++idmap_free_hashtable(struct idmap_hashtable *h) ++{ ++ int i; ++ ++ if (h->h_entries == NULL) ++ return; ++ for (i = 0; i < IDMAP_HASH_SZ; i++) ++ kfree(h->h_entries[i].ih_name); ++ kfree(h->h_entries); ++} ++ + void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; +- int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) +- kfree(idmap->idmap_user_hash.h_entries[i].ih_name); +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) +- kfree(idmap->idmap_group_hash.h_entries[i].ih_name); ++ idmap_free_hashtable(&idmap->idmap_user_hash); ++ idmap_free_hashtable(&idmap->idmap_group_hash); + kfree(idmap); + } + +@@ -401,6 +420,8 @@ + static inline struct idmap_hashent * + idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; + } + +@@ -409,6 +430,8 @@ + { + struct idmap_hashent *he = idmap_name_hash(h, name, len); + ++ if (he == NULL) ++ return NULL; + if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -419,6 +442,8 @@ + static inline struct idmap_hashent * + idmap_id_hash(struct idmap_hashtable* h, __u32 id) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; + } + +@@ -426,6 +451,9 @@ + idmap_lookup_id(struct idmap_hashtable *h, __u32 id) + { + struct idmap_hashent *he = idmap_id_hash(h, id); ++ ++ if (he == NULL) ++ return NULL; + if (he->ih_id != id || he->ih_namelen == 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -441,12 +469,14 @@ + static inline struct idmap_hashent * + idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) + { ++ idmap_alloc_hashtable(h); + return idmap_name_hash(h, name, len); + } + + static inline struct idmap_hashent * + idmap_alloc_id(struct idmap_hashtable *h, __u32 id) + { ++ idmap_alloc_hashtable(h); + return idmap_id_hash(h, id); + } + diff --git a/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch b/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..e7babc2f3 --- /dev/null +++ b/debian/patches/bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,62 @@ +From: Trond Myklebust +Date: Tue, 7 Feb 2012 14:59:05 -0500 +Subject: [1/2] NFSv4: Reduce the footprint of the idmapper + +commit d073e9b541e1ac3f52d72c3a153855d9a9ee3278 upstream. + +Instead of pre-allocating the storage for all the strings, we can +significantly reduce the size of that table by doing the allocation +when we do the downcall. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +[bwh: Backported to 3.2: adjust context in nfs_idmap_delete()] +--- + fs/nfs/idmap.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/nfs/idmap.c ++++ b/fs/nfs/idmap.c +@@ -318,7 +318,7 @@ + unsigned long ih_expires; + __u32 ih_id; + size_t ih_namelen; +- char ih_name[IDMAP_NAMESZ]; ++ const char *ih_name; + }; + + struct idmap_hashtable { +@@ -382,11 +382,16 @@ + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; ++ int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) ++ kfree(idmap->idmap_user_hash.h_entries[i].ih_name); ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) ++ kfree(idmap->idmap_group_hash.h_entries[i].ih_name); + kfree(idmap); + } + +@@ -449,9 +454,14 @@ + idmap_update_entry(struct idmap_hashent *he, const char *name, + size_t namelen, __u32 id) + { ++ char *str = kmalloc(namelen + 1, GFP_KERNEL); ++ if (str == NULL) ++ return; ++ kfree(he->ih_name); + he->ih_id = id; +- memcpy(he->ih_name, name, namelen); +- he->ih_name[namelen] = '\0'; ++ memcpy(str, name, namelen); ++ str[namelen] = '\0'; ++ he->ih_name = str; + he->ih_namelen = namelen; + he->ih_expires = jiffies + nfs_idmap_cache_timeout; + } diff --git a/debian/patches/series-all b/debian/patches/series-all index 1448a6f5b..73aee6ca3 100644 --- a/debian/patches/series-all +++ b/debian/patches/series-all @@ -343,3 +343,6 @@ features/all/hidepid/0001-procfs-parse-mount-options.patch features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch + +bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch +bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch From 59bbce5f6164fe0c18bbd2a82c12ffb5d3605c88 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 8 Jun 2012 12:33:39 +0000 Subject: [PATCH 13/30] Convert source package format to 3.0 (quilt) svn path=/dists/sid/linux/; revision=19098 --- debian/bin/test-patches | 36 +++++++++++++---------- debian/changelog | 5 ++-- debian/patches/{series-all => series} | 0 debian/rules | 3 +- debian/rules.real | 41 +++++++++++++-------------- debian/source/format | 2 +- debian/source/local-options | 1 + 7 files changed, 47 insertions(+), 41 deletions(-) rename debian/patches/{series-all => series} (100%) create mode 100644 debian/source/local-options diff --git a/debian/bin/test-patches b/debian/bin/test-patches index b05e45cf8..fc17ede29 100755 --- a/debian/bin/test-patches +++ b/debian/bin/test-patches @@ -55,26 +55,24 @@ if [ "${version%a~test}" = "$version" ]; then dch -v "$version" --distribution UNRELEASED "Testing patches $*" fi -restrictfeature= +# Make new directory for patches +mkdir -p debian/patches/test + +# Ignore user's .quiltrc +alias quilt='quilt --quiltrc -' + +# Try to clean up any previous test patches if [ "$featureset" = none ]; then - series="series-all" + while quilt top 2>/dev/null | grep -q ^test/; do + quilt delete + done else - series="series-${featureset}" + sed -i '/^test\//d' debian/patches/series-${featureset} fi -# Copy all patches into a new directory +# Prepare a new directory for the patches rm -rf debian/patches/test/ mkdir debian/patches/test -cp -t debian/patches/test/ "$@" - -# Try to clean up any test patches on exit, but also do it now just in case -sed -i '/^test\//d' debian/patches/"$series" -trap "sed -i '/^test\//d' debian/patches/\"$series\"" EXIT - -# Append to patch series -for patch in "$@"; do - echo "test/$(basename "$patch")" >>debian/patches/"$series" -done # Regenerate control and included rules rm debian/control debian/rules.gen @@ -82,9 +80,17 @@ debian/rules debian/control-real && exit 1 || true test -f debian/control test -f debian/rules.gen -# Clean and patch source +# Clean up old build; apply existing patches for featureset debian/rules clean debian/rules source +# Apply the additional patches +for patch in "$@"; do + patch_abs="$(readlink -f "$patch")" + (cd "debian/build/source_${featureset}" && \ + quilt import -P "test/$(basename "$patch")" "$patch_abs" && \ + quilt push --fuzz=0) +done + # Build selected binaries fakeroot make -f debian/rules.gen binary-arch_"$arch"_"$featureset"_"$flavour" diff --git a/debian/changelog b/debian/changelog index 231e435eb..3272fdd40 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,11 @@ linux (3.2.19-2) UNRELEASED; urgency=low - * The "Not Quite So Many Different Version Numbers" release + * The "Confused? You Won't Be" release [ Ben Hutchings ] * Rename source package to 'linux' (Closes: #636010) + * Convert source package format to 3.0 (quilt) + - Convert patch system to quilt, except for the 'orig' patch series * linux-image: Change package name for bugs to 'src:linux' (Closes: #644198) * DFSG: video: Remove nvidiafb and rivafb, which include apparently obfuscated code (Closes: #383481). The nouveau driver supports all @@ -16,7 +18,6 @@ linux (3.2.19-2) UNRELEASED; urgency=low * linux-patch-debian: Remove; it is no longer necessary for GPL compliance and does not work with our current patch management * test-patches: Recognise the rt featureset automatically - * Convert patch system to quilt, except for the 'orig' patch series * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list modules as required even if they are built-in in some configurations * filter: Allow to create sk-unattached filters diff --git a/debian/patches/series-all b/debian/patches/series similarity index 100% rename from debian/patches/series-all rename to debian/patches/series diff --git a/debian/rules b/debian/rules index b7996c5ef..4e0e9c54d 100755 --- a/debian/rules +++ b/debian/rules @@ -43,7 +43,8 @@ TAR_ORIG_NAME = $(SOURCE)_$(VERSION_UPSTREAM).orig.tar.gz TAR_ORIG = $(firstword $(wildcard ../$(TAR_ORIG_NAME)) $(wildcard ../orig/$(TAR_ORIG_NAME))) orig: $(DIR_ORIG) - rsync --delete --exclude debian --exclude .svk --exclude .svn --link-dest=$(DIR_ORIG)/ -a $(DIR_ORIG)/ . + rsync --delete --exclude /debian --exclude .svk --exclude .svn --link-dest=$(DIR_ORIG)/ -a $(DIR_ORIG)/ . + QUILT_PATCHES='$(CURDIR)/debian/patches' quilt push --quiltrc - -a -q --fuzz=0 $(DIR_ORIG): ifeq ($(TAR_ORIG),) diff --git a/debian/rules.real b/debian/rules.real index 543d5b01d..d2915a890 100644 --- a/debian/rules.real +++ b/debian/rules.real @@ -60,37 +60,37 @@ source-featureset: $(STAMPS_DIR)/source_$(FEATURESET) $(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR): $(KCONFIG) python debian/bin/kconfig.py '$@' $(KCONFIG) $(KCONFIG_OPTIONS) -$(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: SOURCE_DIR=$(BUILD_DIR)/source +define copy_source +mkdir -p '$(1)' +cp -al $(filter-out debian .pc .svk .svn, $(wildcard * .[^.]*)) '$(1)' +endef + $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: DIR = $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION) $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: $(STAMPS_DIR)/source rm -rf '$@' '$(DIR)' - cp -al '$(SOURCE_DIR)' '$(DIR)' + $(call copy_source,$(DIR)) chmod -R u+rw,go=rX '$(DIR)' cd '$(BUILD_DIR)'; tar -cjf 'linux-source-$(UPSTREAMVERSION).tar.bz2' 'linux-source-$(UPSTREAMVERSION)' rm -rf '$(DIR)' define patch_cmd -cd '$(DIR)' && QUILT_PATCHES='$(CURDIR)/debian/patches' QUILT_SERIES=series-$(1) quilt push --quiltrc - -a -q --fuzz=1 +cd '$(DIR)' && QUILT_PATCHES='$(CURDIR)/debian/patches' QUILT_SERIES=series-$(1) quilt push --quiltrc - -a -q --fuzz=0 endef -$(STAMPS_DIR)/source: SOURCE_FILES = $(filter-out debian, $(wildcard * .[^.]*)) -$(STAMPS_DIR)/source: DIR = $(BUILD_DIR)/source $(STAMPS_DIR)/source: - rm -rf '$(DIR)' - mkdir -p '$(DIR)' - cp -al $(SOURCE_FILES) '$(DIR)' - $(call patch_cmd,all) + test -d .pc + set +e; quilt unapplied --quiltrc - >/dev/null && echo 'Patch series not fully applied'; test $$? -eq 1 @$(stamp) $(STAMPS_DIR)/source_$(FEATURESET): SOURCE_DIR=$(BUILD_DIR)/source $(STAMPS_DIR)/source_$(FEATURESET): DIR=$(BUILD_DIR)/source_$(FEATURESET) $(STAMPS_DIR)/source_$(FEATURESET): $(STAMPS_DIR)/source + mkdir -p '$(BUILD_DIR)' rm -rf '$(DIR)' ifeq ($(FEATURESET),none) - ln -s source '$(DIR)' + ln -s '$(CURDIR)' '$(DIR)' else - cp -al '$(SOURCE_DIR)' '$(DIR)' - rm -rf '$(DIR)/.pc' + $(call copy_source,$(DIR)) $(call patch_cmd,$(FEATURESET)) endif @$(stamp) @@ -136,13 +136,12 @@ $(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390x-tape: python debian/bin/buildcheck.py $(DIR) $(ARCH) $(FEATURESET) $(FLAVOUR) @$(stamp) -$(STAMPS_DIR)/build-doc: SOURCE_DIR=$(BUILD_DIR)/source $(STAMPS_DIR)/build-doc: DIR=$(BUILD_DIR)/build-doc $(STAMPS_DIR)/build-doc: $(STAMPS_DIR)/source rm -rf $(DIR) - mkdir $(DIR) - +$(MAKE_CLEAN) -C $(SOURCE_DIR) O='$(CURDIR)/$(DIR)' xmldocs - +$(MAKE_CLEAN) -C $(SOURCE_DIR) O='$(CURDIR)/$(DIR)' htmldocs mandocs + mkdir -p $(DIR) + +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' xmldocs + +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' htmldocs mandocs @$(stamp) install-base: @@ -164,14 +163,13 @@ install-dummy: install-doc: PACKAGE_NAME = linux-doc-$(VERSION) install-doc: DIR = $(BUILD_DIR)/build-doc -install-doc: SOURCE_DIR = $(BUILD_DIR)/source install-doc: PACKAGE_DIR = debian/$(PACKAGE_NAME) install-doc: OUT_DIR = $(PACKAGE_DIR)/usr/share/doc/$(PACKAGE_NAME) install-doc: DH_OPTIONS = -p$(PACKAGE_NAME) install-doc: $(STAMPS_DIR)/build-doc dh_prep mkdir -p $(OUT_DIR) - cp -a $(addprefix $(SOURCE_DIR)/, CREDITS MAINTAINERS README REPORTING-BUGS Documentation) $(OUT_DIR) + cp -a CREDITS MAINTAINERS README REPORTING-BUGS Documentation $(OUT_DIR) rm -rf $(OUT_DIR)/Documentation/DocBook cd $(DIR)/Documentation/DocBook; \ find * -name '*.html' -print \ @@ -280,7 +278,6 @@ endif install-libc-dev_$(ARCH): PACKAGE_NAME = linux-libc-dev install-libc-dev_$(ARCH): DH_OPTIONS = -p$(PACKAGE_NAME) -install-libc-dev_$(ARCH): SOURCE_DIR = $(BUILD_DIR)/source install-libc-dev_$(ARCH): DIR = $(BUILD_DIR)/build-libc-dev install-libc-dev_$(ARCH): OUT_DIR = debian/$(PACKAGE_NAME)/usr install-libc-dev_$(ARCH): @@ -288,9 +285,9 @@ install-libc-dev_$(ARCH): dh_testroot dh_prep rm -rf '$(DIR)' - mkdir $(DIR) - +$(MAKE_CLEAN) -C $(SOURCE_DIR) O='$(CURDIR)/$(DIR)' headers_check ARCH=$(KERNEL_ARCH) - +$(MAKE_CLEAN) -C $(SOURCE_DIR) O='$(CURDIR)/$(DIR)' headers_install ARCH=$(KERNEL_ARCH) INSTALL_HDR_PATH='$(CURDIR)'/$(OUT_DIR) + mkdir -p $(DIR) + +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' headers_check ARCH=$(KERNEL_ARCH) + +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' headers_install ARCH=$(KERNEL_ARCH) INSTALL_HDR_PATH='$(CURDIR)'/$(OUT_DIR) rm -rf $(OUT_DIR)/include/drm $(OUT_DIR)/include/scsi find $(OUT_DIR)/include \( -name .install -o -name ..install.cmd \) -execdir rm {} + diff --git a/debian/source/format b/debian/source/format index b9b023757..c3d9f2407 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1,2 +1,2 @@ -1.0 +3.0 (quilt) diff --git a/debian/source/local-options b/debian/source/local-options new file mode 100644 index 000000000..2ee6f0fa1 --- /dev/null +++ b/debian/source/local-options @@ -0,0 +1 @@ +abort-on-upstream-changes From 5007f191edefa1058f16f5f9a1e149fc512a8103 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 8 Jun 2012 12:34:48 +0000 Subject: [PATCH 14/30] Use xz compression for upstream and Debian tarballs svn path=/dists/sid/linux/; revision=19099 --- debian/bin/genorig.py | 4 ++-- debian/changelog | 1 + debian/rules | 4 ++-- debian/source/options | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 debian/source/options diff --git a/debian/bin/genorig.py b/debian/bin/genorig.py index 0a6d6a4cc..6ec909161 100755 --- a/debian/bin/genorig.py +++ b/debian/bin/genorig.py @@ -33,7 +33,7 @@ class Main(object): self.log('Using source name %s, version %s, dfsg %s\n' % (source, version.upstream, self.version_dfsg)) self.orig = '%s-%s' % (source, version.upstream) - self.orig_tar = '%s_%s.orig.tar.gz' % (source, version.upstream) + self.orig_tar = '%s_%s.orig.tar.xz' % (source, version.upstream) self.tag = 'v' + version.linux_upstream_full def __call__(self): @@ -117,7 +117,7 @@ class Main(object): except OSError: pass self.log("Generate tarball %s\n" % out) - cmdline = ['tar -czf', out, '-C', self.dir, self.orig] + cmdline = ['tar -caf', out, '-C', self.dir, self.orig] try: if os.spawnv(os.P_WAIT, '/bin/sh', ['sh', '-c', ' '.join(cmdline)]): raise RuntimeError("Can't patch source") diff --git a/debian/changelog b/debian/changelog index 3272fdd40..f7ce8e080 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * Rename source package to 'linux' (Closes: #636010) * Convert source package format to 3.0 (quilt) - Convert patch system to quilt, except for the 'orig' patch series + - Use xz compression for upstream and Debian tarballs * linux-image: Change package name for bugs to 'src:linux' (Closes: #644198) * DFSG: video: Remove nvidiafb and rivafb, which include apparently obfuscated code (Closes: #383481). The nouveau driver supports all diff --git a/debian/rules b/debian/rules index 4e0e9c54d..458bc289b 100755 --- a/debian/rules +++ b/debian/rules @@ -39,7 +39,7 @@ $(STAMPS_DIR)/build-base: $(STAMPS_DIR)/setup-base @$(stamp) DIR_ORIG = ../orig/$(SOURCE)-$(VERSION_UPSTREAM) -TAR_ORIG_NAME = $(SOURCE)_$(VERSION_UPSTREAM).orig.tar.gz +TAR_ORIG_NAME = $(SOURCE)_$(VERSION_UPSTREAM).orig.tar.xz TAR_ORIG = $(firstword $(wildcard ../$(TAR_ORIG_NAME)) $(wildcard ../orig/$(TAR_ORIG_NAME))) orig: $(DIR_ORIG) @@ -51,7 +51,7 @@ ifeq ($(TAR_ORIG),) $(error Cannot find orig tarball $(TAR_ORIG_NAME)) else mkdir -p ../orig - tar -C ../orig -xzf $(TAR_ORIG) + tar -C ../orig -xaf $(TAR_ORIG) endif maintainerclean: diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 000000000..b7bc1f2b7 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +compression = "xz" From 034b7a318c70f3fb12acfb3bf2f7d18afe67c430 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 8 Jun 2012 13:16:33 +0000 Subject: [PATCH 15/30] Move more changelog items under source package format change svn path=/dists/sid/linux/; revision=19100 --- debian/changelog | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index f7ce8e080..00aa614bf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,10 @@ linux (3.2.19-2) UNRELEASED; urgency=low * Convert source package format to 3.0 (quilt) - Convert patch system to quilt, except for the 'orig' patch series - Use xz compression for upstream and Debian tarballs + - README.source: Update description of patch system to match current + usage + - linux-patch-debian: Remove; it is no longer necessary for GPL + compliance and does not work with our current patch management * linux-image: Change package name for bugs to 'src:linux' (Closes: #644198) * DFSG: video: Remove nvidiafb and rivafb, which include apparently obfuscated code (Closes: #383481). The nouveau driver supports all @@ -15,9 +19,6 @@ linux (3.2.19-2) UNRELEASED; urgency=low * [mipsel/loongson2f] linux-image: Recommend libc6-loongson2f (Closes: #629410) * Build-Depend on kmod or module-init-tools, not just the latter - * README.source: Update description of patch system to match current usage - * linux-patch-debian: Remove; it is no longer necessary for GPL compliance - and does not work with our current patch management * test-patches: Recognise the rt featureset automatically * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list modules as required even if they are built-in in some configurations From 7a82146572a0827cebece33ae07883a10a4535fc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 9 Jun 2012 00:10:28 +0000 Subject: [PATCH 16/30] [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE (Closes: #676360) svn path=/dists/sid/linux/; revision=19101 --- debian/changelog | 2 + ...ead-in-pmd_read_atomic-for-32bit-pae.patch | 112 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 115 insertions(+) create mode 100644 debian/patches/bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch diff --git a/debian/changelog b/debian/changelog index 00aa614bf..6cdd3c6b4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -26,6 +26,8 @@ linux (3.2.19-2) UNRELEASED; urgency=low * net: Backport team driver from Linux 3.5-rc1 * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) + * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + (Closes: #676360) -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 diff --git a/debian/patches/bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch b/debian/patches/bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch new file mode 100644 index 000000000..0a8dfe616 --- /dev/null +++ b/debian/patches/bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch @@ -0,0 +1,112 @@ +From: Andrea Arcangeli +Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + +In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the +mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under +Xen. + +So instead of dealing only with "consistent" pmdvals in +pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually +simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals +where the low 32bit and high 32bit could be inconsistent (to avoid having +to use cmpxchg8b). + +The only guarantee we get from pmd_read_atomic is that if the low part of +the pmd was found null, the high part will be null too (so the pmd will be +considered unstable). And if the low part of the pmd is found "stable" +later, then it means the whole pmd was read atomically (because after a +pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, +and we read the high part after the low part). + +In the 32bit PAE x86 case, it is enough to read the low part of the pmdval +atomically to declare the pmd as "stable" and that's true for THP and no +THP, furthermore in the THP case we also have a barrier() that will +prevent any inconsistent pmdvals to be cached by a later re-read of the +*pmd. + +Signed-off-by: Andrea Arcangeli +Cc: Jonathan Nieder +Cc: Ulrich Obergfell +Cc: Mel Gorman +Cc: Hugh Dickins +Cc: Larry Woodman +Cc: Petr Matousek +Cc: Rik van Riel +Cc: Jan Beulich +Cc: KOSAKI Motohiro +Cc: +Signed-off-by: Andrew Morton +--- + + arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++----------- + include/asm-generic/pgtable.h | 10 ++++++++ + 2 files changed, 27 insertions(+), 13 deletions(-) + +--- a/arch/x86/include/asm/pgtable-3level.h ++++ b/arch/x86/include/asm/pgtable-3level.h +@@ -47,16 +47,26 @@ + * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd + * operations. + * +- * Without THP if the mmap_sem is hold for reading, the +- * pmd can only transition from null to not null while pmd_read_atomic runs. +- * So there's no need of literally reading it atomically. ++ * Without THP if the mmap_sem is hold for reading, the pmd can only ++ * transition from null to not null while pmd_read_atomic runs. So ++ * we can always return atomic pmd values with this function. + * + * With THP if the mmap_sem is hold for reading, the pmd can become +- * THP or null or point to a pte (and in turn become "stable") at any +- * time under pmd_read_atomic, so it's mandatory to read it atomically +- * with cmpxchg8b. ++ * trans_huge or none or point to a pte (and in turn become "stable") ++ * at any time under pmd_read_atomic. We could read it really ++ * atomically here with a atomic64_read for the THP enabled case (and ++ * it would be a whole lot simpler), but to avoid using cmpxchg8b we ++ * only return an atomic pmdval if the low part of the pmdval is later ++ * found stable (i.e. pointing to a pte). And we're returning a none ++ * pmdval if the low part of the pmd is none. In some cases the high ++ * and low part of the pmdval returned may not be consistent if THP is ++ * enabled (the low part may point to previously mapped hugepage, ++ * while the high part may point to a more recently mapped hugepage), ++ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part ++ * of the pmd to be read atomically to decide if the pmd is unstable ++ * or not, with the only exception of when the low part of the pmd is ++ * zero in which case we return a none pmd. + */ +-#ifndef CONFIG_TRANSPARENT_HUGEPAGE + static inline pmd_t pmd_read_atomic(pmd_t *pmdp) + { + pmdval_t ret; +@@ -74,12 +84,6 @@ + + return (pmd_t) { ret }; + } +-#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +-static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +-{ +- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; +-} +-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) + { +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -484,6 +484,16 @@ + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. ++ * ++ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, ++ * pmd_read_atomic is allowed to return a not atomic pmdval ++ * (for example pointing to an hugepage that has never been ++ * mapped in the pmd). The below checks will only care about ++ * the low part of the pmd with 32bit PAE x86 anyway, with the ++ * exception of pmd_none(). So the important thing is that if ++ * the low part of the pmd is found null, the high part will ++ * be also null or the pmd_none() check below would be ++ * confused. + */ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); diff --git a/debian/patches/series b/debian/patches/series index 73aee6ca3..89b40675a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -304,6 +304,7 @@ bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch features/all/AppArmor-compatibility-patch-for-v5-interface.patch bugfix/x86/mm-pmd_read_atomic-fix-32bit-pae-pmd-walk-vs-pmd_populate-smp-race.patch +bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch bugfix/all/mm-fix-vma_resv_map-null-pointer.patch bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch From 14245447ed06865c62252c5b778d4a6c75ac5b41 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 9 Jun 2012 02:17:54 +0000 Subject: [PATCH 17/30] Drop the team driver backport It requires some more intrusive changes to VLAN management which I don't want to try backporting right now. svn path=/dists/sid/linux/; revision=19102 --- debian/changelog | 1 - ...et-introduce-ethernet-teaming-device.patch | 2322 ----------------- ...-rcu_read_lock-when-running-netlink-.patch | 49 - ...am-convert-overall-spinlock-to-mutex.patch | 149 -- ...4-team-replicate-options-on-register.patch | 189 -- .../all/team/0005-team-add-fix_features.patch | 54 - ...am-avoid-using-variable-length-array.patch | 50 - ...am-replace-kmalloc-memcpy-by-kmemdup.patch | 38 - ...net-treewide-use-of-RCU_INIT_POINTER.patch | 28 - ...an_vid_-add-del-and-use-them-instead.patch | 132 - ...unctions-to-do-mass-addition-deletio.patch | 81 - ...team-use-vlan_vids_-addr-del-_by_dev.patch | 53 - ...ly-changed-options-ports-via-netlink.patch | 371 --- .../team/0013-team-Stop-using-NLA_PUT.patch | 108 - .../0014-team-add-binary-option-type.patch | 124 - .../team/0015-team-add-loadbalance-mode.patch | 241 -- ...eam-add-support-for-per-port-options.patch | 687 ----- .../team/0017-team-add-bool-option-type.patch | 137 - ...nkup-and-user_linkup_enabled-per-por.patch | 184 -- ...am-ab-walk-through-port-list-non-rcu.patch | 27 - .../team/0020-team-add-missed-statics.patch | 66 - ...b-let-userspace-care-about-port-macs.patch | 41 - ...2-team-allow-to-enable-disable-ports.patch | 212 -- ...t-option-for-enabling-disabling-port.patch | 54 - debian/patches/series | 30 +- 25 files changed, 3 insertions(+), 5425 deletions(-) delete mode 100644 debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch delete mode 100644 debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch delete mode 100644 debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch delete mode 100644 debian/patches/features/all/team/0004-team-replicate-options-on-register.patch delete mode 100644 debian/patches/features/all/team/0005-team-add-fix_features.patch delete mode 100644 debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch delete mode 100644 debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch delete mode 100644 debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch delete mode 100644 debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch delete mode 100644 debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch delete mode 100644 debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch delete mode 100644 debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch delete mode 100644 debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch delete mode 100644 debian/patches/features/all/team/0014-team-add-binary-option-type.patch delete mode 100644 debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch delete mode 100644 debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch delete mode 100644 debian/patches/features/all/team/0017-team-add-bool-option-type.patch delete mode 100644 debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch delete mode 100644 debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch delete mode 100644 debian/patches/features/all/team/0020-team-add-missed-statics.patch delete mode 100644 debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch delete mode 100644 debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch delete mode 100644 debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch diff --git a/debian/changelog b/debian/changelog index 6cdd3c6b4..10fe0a60f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -23,7 +23,6 @@ linux (3.2.19-2) UNRELEASED; urgency=low * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list modules as required even if they are built-in in some configurations * filter: Allow to create sk-unattached filters - * net: Backport team driver from Linux 3.5-rc1 * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE diff --git a/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch b/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch deleted file mode 100644 index bfc901069..000000000 --- a/debian/patches/features/all/team/0001-net-introduce-ethernet-teaming-device.patch +++ /dev/null @@ -1,2322 +0,0 @@ -From: Jiri Pirko -Date: Fri, 11 Nov 2011 22:16:48 +0000 -Subject: [01/23] net: introduce ethernet teaming device - -commit 3d249d4ca7d0ed6629a135ea1ea21c72286c0d80 upstream. - -This patch introduces new network device called team. It supposes to be -very fast, simple, userspace-driven alternative to existing bonding -driver. - -Userspace library called libteam with couple of demo apps is available -here: -https://github.com/jpirko/libteam -Note it's still in its dipers atm. - -team<->libteam use generic netlink for communication. That and rtnl -suppose to be the only way to configure team device, no sysfs etc. - -Python binding of libteam was recently introduced. -Daemon providing arpmon/miimon active-backup functionality will be -introduced shortly. All what's necessary is already implemented in -kernel team driver. - -v7->v8: - - check ndo_ndo_vlan_rx_[add/kill]_vid functions before calling - them. - - use dev_kfree_skb_any() instead of dev_kfree_skb() - -v6->v7: - - transmit and receive functions are not checked in hot paths. - That also resolves memory leak on transmit when no port is - present - -v5->v6: - - changed couple of _rcu calls to non _rcu ones in non-readers - -v4->v5: - - team_change_mtu() uses team->lock while travesing though port - list - - mac address changes are moved completely to jurisdiction of - userspace daemon. This way the daemon can do FOM1, FOM2 and - possibly other weird things with mac addresses. - Only round-robin mode sets up all ports to bond's address then - enslaved. - - Extended Kconfig text - -v3->v4: - - remove redundant synchronize_rcu from __team_change_mode() - - revert "set and clear of mode_ops happens per pointer, not per - byte" - - extend comment of function __team_change_mode() - -v2->v3: - - team_change_mtu() uses rcu version of list traversal to unwind - - set and clear of mode_ops happens per pointer, not per byte - - port hashlist changed to be embedded into team structure - - error branch in team_port_enter() does cleanup now - - fixed rtln->rtnl - -v1->v2: - - modes are made as modules. Makes team more modular and - extendable. - - several commenters' nitpicks found on v1 were fixed - - several other bugs were fixed. - - note I ignored Eric's comment about roundrobin port selector - as Eric's way may be easily implemented as another mode (mode - "random") in future. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - Documentation/networking/team.txt | 2 + - MAINTAINERS | 7 + - drivers/net/Kconfig | 2 + - drivers/net/Makefile | 1 + - drivers/net/team/Kconfig | 43 + - drivers/net/team/Makefile | 7 + - drivers/net/team/team.c | 1583 +++++++++++++++++++++++++++++ - drivers/net/team/team_mode_activebackup.c | 137 +++ - drivers/net/team/team_mode_roundrobin.c | 107 ++ - include/linux/Kbuild | 1 + - include/linux/if.h | 1 + - include/linux/if_team.h | 242 +++++ - 12 files changed, 2133 insertions(+) - create mode 100644 Documentation/networking/team.txt - create mode 100644 drivers/net/team/Kconfig - create mode 100644 drivers/net/team/Makefile - create mode 100644 drivers/net/team/team.c - create mode 100644 drivers/net/team/team_mode_activebackup.c - create mode 100644 drivers/net/team/team_mode_roundrobin.c - create mode 100644 include/linux/if_team.h - -diff --git a/Documentation/networking/team.txt b/Documentation/networking/team.txt -new file mode 100644 -index 0000000..5a01368 ---- /dev/null -+++ b/Documentation/networking/team.txt -@@ -0,0 +1,2 @@ -+Team devices are driven from userspace via libteam library which is here: -+ https://github.com/jpirko/libteam -diff --git a/MAINTAINERS b/MAINTAINERS -index 4808256..8d94169 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -6484,6 +6484,13 @@ W: http://tcp-lp-mod.sourceforge.net/ - S: Maintained - F: net/ipv4/tcp_lp.c - -+TEAM DRIVER -+M: Jiri Pirko -+L: netdev@vger.kernel.org -+S: Supported -+F: drivers/net/team/ -+F: include/linux/if_team.h -+ - TEGRA SUPPORT - M: Colin Cross - M: Olof Johansson -diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig -index 583f66c..b3020be 100644 ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -125,6 +125,8 @@ config IFB - 'ifb1' etc. - Look at the iproute2 documentation directory for usage etc - -+source "drivers/net/team/Kconfig" -+ - config MACVLAN - tristate "MAC-VLAN support (EXPERIMENTAL)" - depends on EXPERIMENTAL -diff --git a/drivers/net/Makefile b/drivers/net/Makefile -index fa877cd..4e4ebfe 100644 ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_NET) += Space.o loopback.o - obj-$(CONFIG_NETCONSOLE) += netconsole.o - obj-$(CONFIG_PHYLIB) += phy/ - obj-$(CONFIG_RIONET) += rionet.o -+obj-$(CONFIG_NET_TEAM) += team/ - obj-$(CONFIG_TUN) += tun.o - obj-$(CONFIG_VETH) += veth.o - obj-$(CONFIG_VIRTIO_NET) += virtio_net.o -diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig -new file mode 100644 -index 0000000..248a144 ---- /dev/null -+++ b/drivers/net/team/Kconfig -@@ -0,0 +1,43 @@ -+menuconfig NET_TEAM -+ tristate "Ethernet team driver support (EXPERIMENTAL)" -+ depends on EXPERIMENTAL -+ ---help--- -+ This allows one to create virtual interfaces that teams together -+ multiple ethernet devices. -+ -+ Team devices can be added using the "ip" command from the -+ iproute2 package: -+ -+ "ip link add link [ address MAC ] [ NAME ] type team" -+ -+ To compile this driver as a module, choose M here: the module -+ will be called team. -+ -+if NET_TEAM -+ -+config NET_TEAM_MODE_ROUNDROBIN -+ tristate "Round-robin mode support" -+ depends on NET_TEAM -+ ---help--- -+ Basic mode where port used for transmitting packets is selected in -+ round-robin fashion using packet counter. -+ -+ All added ports are setup to have bond's mac address. -+ -+ To compile this team mode as a module, choose M here: the module -+ will be called team_mode_roundrobin. -+ -+config NET_TEAM_MODE_ACTIVEBACKUP -+ tristate "Active-backup mode support" -+ depends on NET_TEAM -+ ---help--- -+ Only one port is active at a time and the rest of ports are used -+ for backup. -+ -+ Mac addresses of ports are not modified. Userspace is responsible -+ to do so. -+ -+ To compile this team mode as a module, choose M here: the module -+ will be called team_mode_activebackup. -+ -+endif # NET_TEAM -diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile -new file mode 100644 -index 0000000..85f2028 ---- /dev/null -+++ b/drivers/net/team/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for the network team driver -+# -+ -+obj-$(CONFIG_NET_TEAM) += team.o -+obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o -+obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -new file mode 100644 -index 0000000..60672bb ---- /dev/null -+++ b/drivers/net/team/team.c -@@ -0,0 +1,1583 @@ -+/* -+ * net/drivers/team/team.c - Network team device driver -+ * Copyright (c) 2011 Jiri Pirko -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRV_NAME "team" -+ -+ -+/********** -+ * Helpers -+ **********/ -+ -+#define team_port_exists(dev) (dev->priv_flags & IFF_TEAM_PORT) -+ -+static struct team_port *team_port_get_rcu(const struct net_device *dev) -+{ -+ struct team_port *port = rcu_dereference(dev->rx_handler_data); -+ -+ return team_port_exists(dev) ? port : NULL; -+} -+ -+static struct team_port *team_port_get_rtnl(const struct net_device *dev) -+{ -+ struct team_port *port = rtnl_dereference(dev->rx_handler_data); -+ -+ return team_port_exists(dev) ? port : NULL; -+} -+ -+/* -+ * Since the ability to change mac address for open port device is tested in -+ * team_port_add, this function can be called without control of return value -+ */ -+static int __set_port_mac(struct net_device *port_dev, -+ const unsigned char *dev_addr) -+{ -+ struct sockaddr addr; -+ -+ memcpy(addr.sa_data, dev_addr, ETH_ALEN); -+ addr.sa_family = ARPHRD_ETHER; -+ return dev_set_mac_address(port_dev, &addr); -+} -+ -+int team_port_set_orig_mac(struct team_port *port) -+{ -+ return __set_port_mac(port->dev, port->orig.dev_addr); -+} -+ -+int team_port_set_team_mac(struct team_port *port) -+{ -+ return __set_port_mac(port->dev, port->team->dev->dev_addr); -+} -+EXPORT_SYMBOL(team_port_set_team_mac); -+ -+ -+/******************* -+ * Options handling -+ *******************/ -+ -+void team_options_register(struct team *team, struct team_option *option, -+ size_t option_count) -+{ -+ int i; -+ -+ for (i = 0; i < option_count; i++, option++) -+ list_add_tail(&option->list, &team->option_list); -+} -+EXPORT_SYMBOL(team_options_register); -+ -+static void __team_options_change_check(struct team *team, -+ struct team_option *changed_option); -+ -+static void __team_options_unregister(struct team *team, -+ struct team_option *option, -+ size_t option_count) -+{ -+ int i; -+ -+ for (i = 0; i < option_count; i++, option++) -+ list_del(&option->list); -+} -+ -+void team_options_unregister(struct team *team, struct team_option *option, -+ size_t option_count) -+{ -+ __team_options_unregister(team, option, option_count); -+ __team_options_change_check(team, NULL); -+} -+EXPORT_SYMBOL(team_options_unregister); -+ -+static int team_option_get(struct team *team, struct team_option *option, -+ void *arg) -+{ -+ return option->getter(team, arg); -+} -+ -+static int team_option_set(struct team *team, struct team_option *option, -+ void *arg) -+{ -+ int err; -+ -+ err = option->setter(team, arg); -+ if (err) -+ return err; -+ -+ __team_options_change_check(team, option); -+ return err; -+} -+ -+/**************** -+ * Mode handling -+ ****************/ -+ -+static LIST_HEAD(mode_list); -+static DEFINE_SPINLOCK(mode_list_lock); -+ -+static struct team_mode *__find_mode(const char *kind) -+{ -+ struct team_mode *mode; -+ -+ list_for_each_entry(mode, &mode_list, list) { -+ if (strcmp(mode->kind, kind) == 0) -+ return mode; -+ } -+ return NULL; -+} -+ -+static bool is_good_mode_name(const char *name) -+{ -+ while (*name != '\0') { -+ if (!isalpha(*name) && !isdigit(*name) && *name != '_') -+ return false; -+ name++; -+ } -+ return true; -+} -+ -+int team_mode_register(struct team_mode *mode) -+{ -+ int err = 0; -+ -+ if (!is_good_mode_name(mode->kind) || -+ mode->priv_size > TEAM_MODE_PRIV_SIZE) -+ return -EINVAL; -+ spin_lock(&mode_list_lock); -+ if (__find_mode(mode->kind)) { -+ err = -EEXIST; -+ goto unlock; -+ } -+ list_add_tail(&mode->list, &mode_list); -+unlock: -+ spin_unlock(&mode_list_lock); -+ return err; -+} -+EXPORT_SYMBOL(team_mode_register); -+ -+int team_mode_unregister(struct team_mode *mode) -+{ -+ spin_lock(&mode_list_lock); -+ list_del_init(&mode->list); -+ spin_unlock(&mode_list_lock); -+ return 0; -+} -+EXPORT_SYMBOL(team_mode_unregister); -+ -+static struct team_mode *team_mode_get(const char *kind) -+{ -+ struct team_mode *mode; -+ -+ spin_lock(&mode_list_lock); -+ mode = __find_mode(kind); -+ if (!mode) { -+ spin_unlock(&mode_list_lock); -+ request_module("team-mode-%s", kind); -+ spin_lock(&mode_list_lock); -+ mode = __find_mode(kind); -+ } -+ if (mode) -+ if (!try_module_get(mode->owner)) -+ mode = NULL; -+ -+ spin_unlock(&mode_list_lock); -+ return mode; -+} -+ -+static void team_mode_put(const struct team_mode *mode) -+{ -+ module_put(mode->owner); -+} -+ -+static bool team_dummy_transmit(struct team *team, struct sk_buff *skb) -+{ -+ dev_kfree_skb_any(skb); -+ return false; -+} -+ -+rx_handler_result_t team_dummy_receive(struct team *team, -+ struct team_port *port, -+ struct sk_buff *skb) -+{ -+ return RX_HANDLER_ANOTHER; -+} -+ -+static void team_adjust_ops(struct team *team) -+{ -+ /* -+ * To avoid checks in rx/tx skb paths, ensure here that non-null and -+ * correct ops are always set. -+ */ -+ -+ if (list_empty(&team->port_list) || -+ !team->mode || !team->mode->ops->transmit) -+ team->ops.transmit = team_dummy_transmit; -+ else -+ team->ops.transmit = team->mode->ops->transmit; -+ -+ if (list_empty(&team->port_list) || -+ !team->mode || !team->mode->ops->receive) -+ team->ops.receive = team_dummy_receive; -+ else -+ team->ops.receive = team->mode->ops->receive; -+} -+ -+/* -+ * We can benefit from the fact that it's ensured no port is present -+ * at the time of mode change. Therefore no packets are in fly so there's no -+ * need to set mode operations in any special way. -+ */ -+static int __team_change_mode(struct team *team, -+ const struct team_mode *new_mode) -+{ -+ /* Check if mode was previously set and do cleanup if so */ -+ if (team->mode) { -+ void (*exit_op)(struct team *team) = team->ops.exit; -+ -+ /* Clear ops area so no callback is called any longer */ -+ memset(&team->ops, 0, sizeof(struct team_mode_ops)); -+ team_adjust_ops(team); -+ -+ if (exit_op) -+ exit_op(team); -+ team_mode_put(team->mode); -+ team->mode = NULL; -+ /* zero private data area */ -+ memset(&team->mode_priv, 0, -+ sizeof(struct team) - offsetof(struct team, mode_priv)); -+ } -+ -+ if (!new_mode) -+ return 0; -+ -+ if (new_mode->ops->init) { -+ int err; -+ -+ err = new_mode->ops->init(team); -+ if (err) -+ return err; -+ } -+ -+ team->mode = new_mode; -+ memcpy(&team->ops, new_mode->ops, sizeof(struct team_mode_ops)); -+ team_adjust_ops(team); -+ -+ return 0; -+} -+ -+static int team_change_mode(struct team *team, const char *kind) -+{ -+ struct team_mode *new_mode; -+ struct net_device *dev = team->dev; -+ int err; -+ -+ if (!list_empty(&team->port_list)) { -+ netdev_err(dev, "No ports can be present during mode change\n"); -+ return -EBUSY; -+ } -+ -+ if (team->mode && strcmp(team->mode->kind, kind) == 0) { -+ netdev_err(dev, "Unable to change to the same mode the team is in\n"); -+ return -EINVAL; -+ } -+ -+ new_mode = team_mode_get(kind); -+ if (!new_mode) { -+ netdev_err(dev, "Mode \"%s\" not found\n", kind); -+ return -EINVAL; -+ } -+ -+ err = __team_change_mode(team, new_mode); -+ if (err) { -+ netdev_err(dev, "Failed to change to mode \"%s\"\n", kind); -+ team_mode_put(new_mode); -+ return err; -+ } -+ -+ netdev_info(dev, "Mode changed to \"%s\"\n", kind); -+ return 0; -+} -+ -+ -+/************************ -+ * Rx path frame handler -+ ************************/ -+ -+/* note: already called with rcu_read_lock */ -+static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) -+{ -+ struct sk_buff *skb = *pskb; -+ struct team_port *port; -+ struct team *team; -+ rx_handler_result_t res; -+ -+ skb = skb_share_check(skb, GFP_ATOMIC); -+ if (!skb) -+ return RX_HANDLER_CONSUMED; -+ -+ *pskb = skb; -+ -+ port = team_port_get_rcu(skb->dev); -+ team = port->team; -+ -+ res = team->ops.receive(team, port, skb); -+ if (res == RX_HANDLER_ANOTHER) { -+ struct team_pcpu_stats *pcpu_stats; -+ -+ pcpu_stats = this_cpu_ptr(team->pcpu_stats); -+ u64_stats_update_begin(&pcpu_stats->syncp); -+ pcpu_stats->rx_packets++; -+ pcpu_stats->rx_bytes += skb->len; -+ if (skb->pkt_type == PACKET_MULTICAST) -+ pcpu_stats->rx_multicast++; -+ u64_stats_update_end(&pcpu_stats->syncp); -+ -+ skb->dev = team->dev; -+ } else { -+ this_cpu_inc(team->pcpu_stats->rx_dropped); -+ } -+ -+ return res; -+} -+ -+ -+/**************** -+ * Port handling -+ ****************/ -+ -+static bool team_port_find(const struct team *team, -+ const struct team_port *port) -+{ -+ struct team_port *cur; -+ -+ list_for_each_entry(cur, &team->port_list, list) -+ if (cur == port) -+ return true; -+ return false; -+} -+ -+/* -+ * Add/delete port to the team port list. Write guarded by rtnl_lock. -+ * Takes care of correct port->index setup (might be racy). -+ */ -+static void team_port_list_add_port(struct team *team, -+ struct team_port *port) -+{ -+ port->index = team->port_count++; -+ hlist_add_head_rcu(&port->hlist, -+ team_port_index_hash(team, port->index)); -+ list_add_tail_rcu(&port->list, &team->port_list); -+} -+ -+static void __reconstruct_port_hlist(struct team *team, int rm_index) -+{ -+ int i; -+ struct team_port *port; -+ -+ for (i = rm_index + 1; i < team->port_count; i++) { -+ port = team_get_port_by_index(team, i); -+ hlist_del_rcu(&port->hlist); -+ port->index--; -+ hlist_add_head_rcu(&port->hlist, -+ team_port_index_hash(team, port->index)); -+ } -+} -+ -+static void team_port_list_del_port(struct team *team, -+ struct team_port *port) -+{ -+ int rm_index = port->index; -+ -+ hlist_del_rcu(&port->hlist); -+ list_del_rcu(&port->list); -+ __reconstruct_port_hlist(team, rm_index); -+ team->port_count--; -+} -+ -+#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ -+ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ -+ NETIF_F_HIGHDMA | NETIF_F_LRO) -+ -+static void __team_compute_features(struct team *team) -+{ -+ struct team_port *port; -+ u32 vlan_features = TEAM_VLAN_FEATURES; -+ unsigned short max_hard_header_len = ETH_HLEN; -+ -+ list_for_each_entry(port, &team->port_list, list) { -+ vlan_features = netdev_increment_features(vlan_features, -+ port->dev->vlan_features, -+ TEAM_VLAN_FEATURES); -+ -+ if (port->dev->hard_header_len > max_hard_header_len) -+ max_hard_header_len = port->dev->hard_header_len; -+ } -+ -+ team->dev->vlan_features = vlan_features; -+ team->dev->hard_header_len = max_hard_header_len; -+ -+ netdev_change_features(team->dev); -+} -+ -+static void team_compute_features(struct team *team) -+{ -+ spin_lock(&team->lock); -+ __team_compute_features(team); -+ spin_unlock(&team->lock); -+} -+ -+static int team_port_enter(struct team *team, struct team_port *port) -+{ -+ int err = 0; -+ -+ dev_hold(team->dev); -+ port->dev->priv_flags |= IFF_TEAM_PORT; -+ if (team->ops.port_enter) { -+ err = team->ops.port_enter(team, port); -+ if (err) { -+ netdev_err(team->dev, "Device %s failed to enter team mode\n", -+ port->dev->name); -+ goto err_port_enter; -+ } -+ } -+ -+ return 0; -+ -+err_port_enter: -+ port->dev->priv_flags &= ~IFF_TEAM_PORT; -+ dev_put(team->dev); -+ -+ return err; -+} -+ -+static void team_port_leave(struct team *team, struct team_port *port) -+{ -+ if (team->ops.port_leave) -+ team->ops.port_leave(team, port); -+ port->dev->priv_flags &= ~IFF_TEAM_PORT; -+ dev_put(team->dev); -+} -+ -+static void __team_port_change_check(struct team_port *port, bool linkup); -+ -+static int team_port_add(struct team *team, struct net_device *port_dev) -+{ -+ struct net_device *dev = team->dev; -+ struct team_port *port; -+ char *portname = port_dev->name; -+ int err; -+ -+ if (port_dev->flags & IFF_LOOPBACK || -+ port_dev->type != ARPHRD_ETHER) { -+ netdev_err(dev, "Device %s is of an unsupported type\n", -+ portname); -+ return -EINVAL; -+ } -+ -+ if (team_port_exists(port_dev)) { -+ netdev_err(dev, "Device %s is already a port " -+ "of a team device\n", portname); -+ return -EBUSY; -+ } -+ -+ if (port_dev->flags & IFF_UP) { -+ netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", -+ portname); -+ return -EBUSY; -+ } -+ -+ port = kzalloc(sizeof(struct team_port), GFP_KERNEL); -+ if (!port) -+ return -ENOMEM; -+ -+ port->dev = port_dev; -+ port->team = team; -+ -+ port->orig.mtu = port_dev->mtu; -+ err = dev_set_mtu(port_dev, dev->mtu); -+ if (err) { -+ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); -+ goto err_set_mtu; -+ } -+ -+ memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); -+ -+ err = team_port_enter(team, port); -+ if (err) { -+ netdev_err(dev, "Device %s failed to enter team mode\n", -+ portname); -+ goto err_port_enter; -+ } -+ -+ err = dev_open(port_dev); -+ if (err) { -+ netdev_dbg(dev, "Device %s opening failed\n", -+ portname); -+ goto err_dev_open; -+ } -+ -+ err = netdev_set_master(port_dev, dev); -+ if (err) { -+ netdev_err(dev, "Device %s failed to set master\n", portname); -+ goto err_set_master; -+ } -+ -+ err = netdev_rx_handler_register(port_dev, team_handle_frame, -+ port); -+ if (err) { -+ netdev_err(dev, "Device %s failed to register rx_handler\n", -+ portname); -+ goto err_handler_register; -+ } -+ -+ team_port_list_add_port(team, port); -+ team_adjust_ops(team); -+ __team_compute_features(team); -+ __team_port_change_check(port, !!netif_carrier_ok(port_dev)); -+ -+ netdev_info(dev, "Port device %s added\n", portname); -+ -+ return 0; -+ -+err_handler_register: -+ netdev_set_master(port_dev, NULL); -+ -+err_set_master: -+ dev_close(port_dev); -+ -+err_dev_open: -+ team_port_leave(team, port); -+ team_port_set_orig_mac(port); -+ -+err_port_enter: -+ dev_set_mtu(port_dev, port->orig.mtu); -+ -+err_set_mtu: -+ kfree(port); -+ -+ return err; -+} -+ -+static int team_port_del(struct team *team, struct net_device *port_dev) -+{ -+ struct net_device *dev = team->dev; -+ struct team_port *port; -+ char *portname = port_dev->name; -+ -+ port = team_port_get_rtnl(port_dev); -+ if (!port || !team_port_find(team, port)) { -+ netdev_err(dev, "Device %s does not act as a port of this team\n", -+ portname); -+ return -ENOENT; -+ } -+ -+ __team_port_change_check(port, false); -+ team_port_list_del_port(team, port); -+ team_adjust_ops(team); -+ netdev_rx_handler_unregister(port_dev); -+ netdev_set_master(port_dev, NULL); -+ dev_close(port_dev); -+ team_port_leave(team, port); -+ team_port_set_orig_mac(port); -+ dev_set_mtu(port_dev, port->orig.mtu); -+ synchronize_rcu(); -+ kfree(port); -+ netdev_info(dev, "Port device %s removed\n", portname); -+ __team_compute_features(team); -+ -+ return 0; -+} -+ -+ -+/***************** -+ * Net device ops -+ *****************/ -+ -+static const char team_no_mode_kind[] = "*NOMODE*"; -+ -+static int team_mode_option_get(struct team *team, void *arg) -+{ -+ const char **str = arg; -+ -+ *str = team->mode ? team->mode->kind : team_no_mode_kind; -+ return 0; -+} -+ -+static int team_mode_option_set(struct team *team, void *arg) -+{ -+ const char **str = arg; -+ -+ return team_change_mode(team, *str); -+} -+ -+static struct team_option team_options[] = { -+ { -+ .name = "mode", -+ .type = TEAM_OPTION_TYPE_STRING, -+ .getter = team_mode_option_get, -+ .setter = team_mode_option_set, -+ }, -+}; -+ -+static int team_init(struct net_device *dev) -+{ -+ struct team *team = netdev_priv(dev); -+ int i; -+ -+ team->dev = dev; -+ spin_lock_init(&team->lock); -+ -+ team->pcpu_stats = alloc_percpu(struct team_pcpu_stats); -+ if (!team->pcpu_stats) -+ return -ENOMEM; -+ -+ for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) -+ INIT_HLIST_HEAD(&team->port_hlist[i]); -+ INIT_LIST_HEAD(&team->port_list); -+ -+ team_adjust_ops(team); -+ -+ INIT_LIST_HEAD(&team->option_list); -+ team_options_register(team, team_options, ARRAY_SIZE(team_options)); -+ netif_carrier_off(dev); -+ -+ return 0; -+} -+ -+static void team_uninit(struct net_device *dev) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ struct team_port *tmp; -+ -+ spin_lock(&team->lock); -+ list_for_each_entry_safe(port, tmp, &team->port_list, list) -+ team_port_del(team, port->dev); -+ -+ __team_change_mode(team, NULL); /* cleanup */ -+ __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); -+ spin_unlock(&team->lock); -+} -+ -+static void team_destructor(struct net_device *dev) -+{ -+ struct team *team = netdev_priv(dev); -+ -+ free_percpu(team->pcpu_stats); -+ free_netdev(dev); -+} -+ -+static int team_open(struct net_device *dev) -+{ -+ netif_carrier_on(dev); -+ return 0; -+} -+ -+static int team_close(struct net_device *dev) -+{ -+ netif_carrier_off(dev); -+ return 0; -+} -+ -+/* -+ * note: already called with rcu_read_lock -+ */ -+static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct team *team = netdev_priv(dev); -+ bool tx_success = false; -+ unsigned int len = skb->len; -+ -+ tx_success = team->ops.transmit(team, skb); -+ if (tx_success) { -+ struct team_pcpu_stats *pcpu_stats; -+ -+ pcpu_stats = this_cpu_ptr(team->pcpu_stats); -+ u64_stats_update_begin(&pcpu_stats->syncp); -+ pcpu_stats->tx_packets++; -+ pcpu_stats->tx_bytes += len; -+ u64_stats_update_end(&pcpu_stats->syncp); -+ } else { -+ this_cpu_inc(team->pcpu_stats->tx_dropped); -+ } -+ -+ return NETDEV_TX_OK; -+} -+ -+static void team_change_rx_flags(struct net_device *dev, int change) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ int inc; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ if (change & IFF_PROMISC) { -+ inc = dev->flags & IFF_PROMISC ? 1 : -1; -+ dev_set_promiscuity(port->dev, inc); -+ } -+ if (change & IFF_ALLMULTI) { -+ inc = dev->flags & IFF_ALLMULTI ? 1 : -1; -+ dev_set_allmulti(port->dev, inc); -+ } -+ } -+ rcu_read_unlock(); -+} -+ -+static void team_set_rx_mode(struct net_device *dev) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ dev_uc_sync(port->dev, dev); -+ dev_mc_sync(port->dev, dev); -+ } -+ rcu_read_unlock(); -+} -+ -+static int team_set_mac_address(struct net_device *dev, void *p) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ struct sockaddr *addr = p; -+ -+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) -+ if (team->ops.port_change_mac) -+ team->ops.port_change_mac(team, port); -+ rcu_read_unlock(); -+ return 0; -+} -+ -+static int team_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ int err; -+ -+ /* -+ * Alhough this is reader, it's guarded by team lock. It's not possible -+ * to traverse list in reverse under rcu_read_lock -+ */ -+ spin_lock(&team->lock); -+ list_for_each_entry(port, &team->port_list, list) { -+ err = dev_set_mtu(port->dev, new_mtu); -+ if (err) { -+ netdev_err(dev, "Device %s failed to change mtu", -+ port->dev->name); -+ goto unwind; -+ } -+ } -+ spin_unlock(&team->lock); -+ -+ dev->mtu = new_mtu; -+ -+ return 0; -+ -+unwind: -+ list_for_each_entry_continue_reverse(port, &team->port_list, list) -+ dev_set_mtu(port->dev, dev->mtu); -+ spin_unlock(&team->lock); -+ -+ return err; -+} -+ -+static struct rtnl_link_stats64 * -+team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_pcpu_stats *p; -+ u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes; -+ u32 rx_dropped = 0, tx_dropped = 0; -+ unsigned int start; -+ int i; -+ -+ for_each_possible_cpu(i) { -+ p = per_cpu_ptr(team->pcpu_stats, i); -+ do { -+ start = u64_stats_fetch_begin_bh(&p->syncp); -+ rx_packets = p->rx_packets; -+ rx_bytes = p->rx_bytes; -+ rx_multicast = p->rx_multicast; -+ tx_packets = p->tx_packets; -+ tx_bytes = p->tx_bytes; -+ } while (u64_stats_fetch_retry_bh(&p->syncp, start)); -+ -+ stats->rx_packets += rx_packets; -+ stats->rx_bytes += rx_bytes; -+ stats->multicast += rx_multicast; -+ stats->tx_packets += tx_packets; -+ stats->tx_bytes += tx_bytes; -+ /* -+ * rx_dropped & tx_dropped are u32, updated -+ * without syncp protection. -+ */ -+ rx_dropped += p->rx_dropped; -+ tx_dropped += p->tx_dropped; -+ } -+ stats->rx_dropped = rx_dropped; -+ stats->tx_dropped = tx_dropped; -+ return stats; -+} -+ -+static void team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ const struct net_device_ops *ops = port->dev->netdev_ops; -+ -+ if (ops->ndo_vlan_rx_add_vid) -+ ops->ndo_vlan_rx_add_vid(port->dev, vid); -+ } -+ rcu_read_unlock(); -+} -+ -+static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -+{ -+ struct team *team = netdev_priv(dev); -+ struct team_port *port; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ const struct net_device_ops *ops = port->dev->netdev_ops; -+ -+ if (ops->ndo_vlan_rx_kill_vid) -+ ops->ndo_vlan_rx_kill_vid(port->dev, vid); -+ } -+ rcu_read_unlock(); -+} -+ -+static int team_add_slave(struct net_device *dev, struct net_device *port_dev) -+{ -+ struct team *team = netdev_priv(dev); -+ int err; -+ -+ spin_lock(&team->lock); -+ err = team_port_add(team, port_dev); -+ spin_unlock(&team->lock); -+ return err; -+} -+ -+static int team_del_slave(struct net_device *dev, struct net_device *port_dev) -+{ -+ struct team *team = netdev_priv(dev); -+ int err; -+ -+ spin_lock(&team->lock); -+ err = team_port_del(team, port_dev); -+ spin_unlock(&team->lock); -+ return err; -+} -+ -+static const struct net_device_ops team_netdev_ops = { -+ .ndo_init = team_init, -+ .ndo_uninit = team_uninit, -+ .ndo_open = team_open, -+ .ndo_stop = team_close, -+ .ndo_start_xmit = team_xmit, -+ .ndo_change_rx_flags = team_change_rx_flags, -+ .ndo_set_rx_mode = team_set_rx_mode, -+ .ndo_set_mac_address = team_set_mac_address, -+ .ndo_change_mtu = team_change_mtu, -+ .ndo_get_stats64 = team_get_stats64, -+ .ndo_vlan_rx_add_vid = team_vlan_rx_add_vid, -+ .ndo_vlan_rx_kill_vid = team_vlan_rx_kill_vid, -+ .ndo_add_slave = team_add_slave, -+ .ndo_del_slave = team_del_slave, -+}; -+ -+ -+/*********************** -+ * rt netlink interface -+ ***********************/ -+ -+static void team_setup(struct net_device *dev) -+{ -+ ether_setup(dev); -+ -+ dev->netdev_ops = &team_netdev_ops; -+ dev->destructor = team_destructor; -+ dev->tx_queue_len = 0; -+ dev->flags |= IFF_MULTICAST; -+ dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); -+ -+ /* -+ * Indicate we support unicast address filtering. That way core won't -+ * bring us to promisc mode in case a unicast addr is added. -+ * Let this up to underlay drivers. -+ */ -+ dev->priv_flags |= IFF_UNICAST_FLT; -+ -+ dev->features |= NETIF_F_LLTX; -+ dev->features |= NETIF_F_GRO; -+ dev->hw_features = NETIF_F_HW_VLAN_TX | -+ NETIF_F_HW_VLAN_RX | -+ NETIF_F_HW_VLAN_FILTER; -+ -+ dev->features |= dev->hw_features; -+} -+ -+static int team_newlink(struct net *src_net, struct net_device *dev, -+ struct nlattr *tb[], struct nlattr *data[]) -+{ -+ int err; -+ -+ if (tb[IFLA_ADDRESS] == NULL) -+ random_ether_addr(dev->dev_addr); -+ -+ err = register_netdevice(dev); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+static int team_validate(struct nlattr *tb[], struct nlattr *data[]) -+{ -+ if (tb[IFLA_ADDRESS]) { -+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) -+ return -EINVAL; -+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) -+ return -EADDRNOTAVAIL; -+ } -+ return 0; -+} -+ -+static struct rtnl_link_ops team_link_ops __read_mostly = { -+ .kind = DRV_NAME, -+ .priv_size = sizeof(struct team), -+ .setup = team_setup, -+ .newlink = team_newlink, -+ .validate = team_validate, -+}; -+ -+ -+/*********************************** -+ * Generic netlink custom interface -+ ***********************************/ -+ -+static struct genl_family team_nl_family = { -+ .id = GENL_ID_GENERATE, -+ .name = TEAM_GENL_NAME, -+ .version = TEAM_GENL_VERSION, -+ .maxattr = TEAM_ATTR_MAX, -+ .netnsok = true, -+}; -+ -+static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = { -+ [TEAM_ATTR_UNSPEC] = { .type = NLA_UNSPEC, }, -+ [TEAM_ATTR_TEAM_IFINDEX] = { .type = NLA_U32 }, -+ [TEAM_ATTR_LIST_OPTION] = { .type = NLA_NESTED }, -+ [TEAM_ATTR_LIST_PORT] = { .type = NLA_NESTED }, -+}; -+ -+static const struct nla_policy -+team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { -+ [TEAM_ATTR_OPTION_UNSPEC] = { .type = NLA_UNSPEC, }, -+ [TEAM_ATTR_OPTION_NAME] = { -+ .type = NLA_STRING, -+ .len = TEAM_STRING_MAX_LEN, -+ }, -+ [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, -+ [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, -+ [TEAM_ATTR_OPTION_DATA] = { -+ .type = NLA_BINARY, -+ .len = TEAM_STRING_MAX_LEN, -+ }, -+}; -+ -+static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct sk_buff *msg; -+ void *hdr; -+ int err; -+ -+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); -+ if (!msg) -+ return -ENOMEM; -+ -+ hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, -+ &team_nl_family, 0, TEAM_CMD_NOOP); -+ if (IS_ERR(hdr)) { -+ err = PTR_ERR(hdr); -+ goto err_msg_put; -+ } -+ -+ genlmsg_end(msg, hdr); -+ -+ return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); -+ -+err_msg_put: -+ nlmsg_free(msg); -+ -+ return err; -+} -+ -+/* -+ * Netlink cmd functions should be locked by following two functions. -+ * To ensure team_uninit would not be called in between, hold rcu_read_lock -+ * all the time. -+ */ -+static struct team *team_nl_team_get(struct genl_info *info) -+{ -+ struct net *net = genl_info_net(info); -+ int ifindex; -+ struct net_device *dev; -+ struct team *team; -+ -+ if (!info->attrs[TEAM_ATTR_TEAM_IFINDEX]) -+ return NULL; -+ -+ ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]); -+ rcu_read_lock(); -+ dev = dev_get_by_index_rcu(net, ifindex); -+ if (!dev || dev->netdev_ops != &team_netdev_ops) { -+ rcu_read_unlock(); -+ return NULL; -+ } -+ -+ team = netdev_priv(dev); -+ spin_lock(&team->lock); -+ return team; -+} -+ -+static void team_nl_team_put(struct team *team) -+{ -+ spin_unlock(&team->lock); -+ rcu_read_unlock(); -+} -+ -+static int team_nl_send_generic(struct genl_info *info, struct team *team, -+ int (*fill_func)(struct sk_buff *skb, -+ struct genl_info *info, -+ int flags, struct team *team)) -+{ -+ struct sk_buff *skb; -+ int err; -+ -+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); -+ if (!skb) -+ return -ENOMEM; -+ -+ err = fill_func(skb, info, NLM_F_ACK, team); -+ if (err < 0) -+ goto err_fill; -+ -+ err = genlmsg_unicast(genl_info_net(info), skb, info->snd_pid); -+ return err; -+ -+err_fill: -+ nlmsg_free(skb); -+ return err; -+} -+ -+static int team_nl_fill_options_get_changed(struct sk_buff *skb, -+ u32 pid, u32 seq, int flags, -+ struct team *team, -+ struct team_option *changed_option) -+{ -+ struct nlattr *option_list; -+ void *hdr; -+ struct team_option *option; -+ -+ hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, -+ TEAM_CMD_OPTIONS_GET); -+ if (IS_ERR(hdr)) -+ return PTR_ERR(hdr); -+ -+ NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); -+ option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION); -+ if (!option_list) -+ return -EMSGSIZE; -+ -+ list_for_each_entry(option, &team->option_list, list) { -+ struct nlattr *option_item; -+ long arg; -+ -+ option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); -+ if (!option_item) -+ goto nla_put_failure; -+ NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); -+ if (option == changed_option) -+ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); -+ switch (option->type) { -+ case TEAM_OPTION_TYPE_U32: -+ NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); -+ team_option_get(team, option, &arg); -+ NLA_PUT_U32(skb, TEAM_ATTR_OPTION_DATA, arg); -+ break; -+ case TEAM_OPTION_TYPE_STRING: -+ NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING); -+ team_option_get(team, option, &arg); -+ NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_DATA, -+ (char *) arg); -+ break; -+ default: -+ BUG(); -+ } -+ nla_nest_end(skb, option_item); -+ } -+ -+ nla_nest_end(skb, option_list); -+ return genlmsg_end(skb, hdr); -+ -+nla_put_failure: -+ genlmsg_cancel(skb, hdr); -+ return -EMSGSIZE; -+} -+ -+static int team_nl_fill_options_get(struct sk_buff *skb, -+ struct genl_info *info, int flags, -+ struct team *team) -+{ -+ return team_nl_fill_options_get_changed(skb, info->snd_pid, -+ info->snd_seq, NLM_F_ACK, -+ team, NULL); -+} -+ -+static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct team *team; -+ int err; -+ -+ team = team_nl_team_get(info); -+ if (!team) -+ return -EINVAL; -+ -+ err = team_nl_send_generic(info, team, team_nl_fill_options_get); -+ -+ team_nl_team_put(team); -+ -+ return err; -+} -+ -+static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct team *team; -+ int err = 0; -+ int i; -+ struct nlattr *nl_option; -+ -+ team = team_nl_team_get(info); -+ if (!team) -+ return -EINVAL; -+ -+ err = -EINVAL; -+ if (!info->attrs[TEAM_ATTR_LIST_OPTION]) { -+ err = -EINVAL; -+ goto team_put; -+ } -+ -+ nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { -+ struct nlattr *mode_attrs[TEAM_ATTR_OPTION_MAX + 1]; -+ enum team_option_type opt_type; -+ struct team_option *option; -+ char *opt_name; -+ bool opt_found = false; -+ -+ if (nla_type(nl_option) != TEAM_ATTR_ITEM_OPTION) { -+ err = -EINVAL; -+ goto team_put; -+ } -+ err = nla_parse_nested(mode_attrs, TEAM_ATTR_OPTION_MAX, -+ nl_option, team_nl_option_policy); -+ if (err) -+ goto team_put; -+ if (!mode_attrs[TEAM_ATTR_OPTION_NAME] || -+ !mode_attrs[TEAM_ATTR_OPTION_TYPE] || -+ !mode_attrs[TEAM_ATTR_OPTION_DATA]) { -+ err = -EINVAL; -+ goto team_put; -+ } -+ switch (nla_get_u8(mode_attrs[TEAM_ATTR_OPTION_TYPE])) { -+ case NLA_U32: -+ opt_type = TEAM_OPTION_TYPE_U32; -+ break; -+ case NLA_STRING: -+ opt_type = TEAM_OPTION_TYPE_STRING; -+ break; -+ default: -+ goto team_put; -+ } -+ -+ opt_name = nla_data(mode_attrs[TEAM_ATTR_OPTION_NAME]); -+ list_for_each_entry(option, &team->option_list, list) { -+ long arg; -+ struct nlattr *opt_data_attr; -+ -+ if (option->type != opt_type || -+ strcmp(option->name, opt_name)) -+ continue; -+ opt_found = true; -+ opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; -+ switch (opt_type) { -+ case TEAM_OPTION_TYPE_U32: -+ arg = nla_get_u32(opt_data_attr); -+ break; -+ case TEAM_OPTION_TYPE_STRING: -+ arg = (long) nla_data(opt_data_attr); -+ break; -+ default: -+ BUG(); -+ } -+ err = team_option_set(team, option, &arg); -+ if (err) -+ goto team_put; -+ } -+ if (!opt_found) { -+ err = -ENOENT; -+ goto team_put; -+ } -+ } -+ -+team_put: -+ team_nl_team_put(team); -+ -+ return err; -+} -+ -+static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, -+ u32 pid, u32 seq, int flags, -+ struct team *team, -+ struct team_port *changed_port) -+{ -+ struct nlattr *port_list; -+ void *hdr; -+ struct team_port *port; -+ -+ hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, -+ TEAM_CMD_PORT_LIST_GET); -+ if (IS_ERR(hdr)) -+ return PTR_ERR(hdr); -+ -+ NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); -+ port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT); -+ if (!port_list) -+ return -EMSGSIZE; -+ -+ list_for_each_entry(port, &team->port_list, list) { -+ struct nlattr *port_item; -+ -+ port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); -+ if (!port_item) -+ goto nla_put_failure; -+ NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); -+ if (port == changed_port) -+ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); -+ if (port->linkup) -+ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); -+ NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); -+ NLA_PUT_U8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex); -+ nla_nest_end(skb, port_item); -+ } -+ -+ nla_nest_end(skb, port_list); -+ return genlmsg_end(skb, hdr); -+ -+nla_put_failure: -+ genlmsg_cancel(skb, hdr); -+ return -EMSGSIZE; -+} -+ -+static int team_nl_fill_port_list_get(struct sk_buff *skb, -+ struct genl_info *info, int flags, -+ struct team *team) -+{ -+ return team_nl_fill_port_list_get_changed(skb, info->snd_pid, -+ info->snd_seq, NLM_F_ACK, -+ team, NULL); -+} -+ -+static int team_nl_cmd_port_list_get(struct sk_buff *skb, -+ struct genl_info *info) -+{ -+ struct team *team; -+ int err; -+ -+ team = team_nl_team_get(info); -+ if (!team) -+ return -EINVAL; -+ -+ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get); -+ -+ team_nl_team_put(team); -+ -+ return err; -+} -+ -+static struct genl_ops team_nl_ops[] = { -+ { -+ .cmd = TEAM_CMD_NOOP, -+ .doit = team_nl_cmd_noop, -+ .policy = team_nl_policy, -+ }, -+ { -+ .cmd = TEAM_CMD_OPTIONS_SET, -+ .doit = team_nl_cmd_options_set, -+ .policy = team_nl_policy, -+ .flags = GENL_ADMIN_PERM, -+ }, -+ { -+ .cmd = TEAM_CMD_OPTIONS_GET, -+ .doit = team_nl_cmd_options_get, -+ .policy = team_nl_policy, -+ .flags = GENL_ADMIN_PERM, -+ }, -+ { -+ .cmd = TEAM_CMD_PORT_LIST_GET, -+ .doit = team_nl_cmd_port_list_get, -+ .policy = team_nl_policy, -+ .flags = GENL_ADMIN_PERM, -+ }, -+}; -+ -+static struct genl_multicast_group team_change_event_mcgrp = { -+ .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, -+}; -+ -+static int team_nl_send_event_options_get(struct team *team, -+ struct team_option *changed_option) -+{ -+ struct sk_buff *skb; -+ int err; -+ struct net *net = dev_net(team->dev); -+ -+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); -+ if (!skb) -+ return -ENOMEM; -+ -+ err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team, -+ changed_option); -+ if (err < 0) -+ goto err_fill; -+ -+ err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, -+ GFP_KERNEL); -+ return err; -+ -+err_fill: -+ nlmsg_free(skb); -+ return err; -+} -+ -+static int team_nl_send_event_port_list_get(struct team_port *port) -+{ -+ struct sk_buff *skb; -+ int err; -+ struct net *net = dev_net(port->team->dev); -+ -+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); -+ if (!skb) -+ return -ENOMEM; -+ -+ err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0, -+ port->team, port); -+ if (err < 0) -+ goto err_fill; -+ -+ err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, -+ GFP_KERNEL); -+ return err; -+ -+err_fill: -+ nlmsg_free(skb); -+ return err; -+} -+ -+static int team_nl_init(void) -+{ -+ int err; -+ -+ err = genl_register_family_with_ops(&team_nl_family, team_nl_ops, -+ ARRAY_SIZE(team_nl_ops)); -+ if (err) -+ return err; -+ -+ err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp); -+ if (err) -+ goto err_change_event_grp_reg; -+ -+ return 0; -+ -+err_change_event_grp_reg: -+ genl_unregister_family(&team_nl_family); -+ -+ return err; -+} -+ -+static void team_nl_fini(void) -+{ -+ genl_unregister_family(&team_nl_family); -+} -+ -+ -+/****************** -+ * Change checkers -+ ******************/ -+ -+static void __team_options_change_check(struct team *team, -+ struct team_option *changed_option) -+{ -+ int err; -+ -+ err = team_nl_send_event_options_get(team, changed_option); -+ if (err) -+ netdev_warn(team->dev, "Failed to send options change via netlink\n"); -+} -+ -+/* rtnl lock is held */ -+static void __team_port_change_check(struct team_port *port, bool linkup) -+{ -+ int err; -+ -+ if (port->linkup == linkup) -+ return; -+ -+ port->linkup = linkup; -+ if (linkup) { -+ struct ethtool_cmd ecmd; -+ -+ err = __ethtool_get_settings(port->dev, &ecmd); -+ if (!err) { -+ port->speed = ethtool_cmd_speed(&ecmd); -+ port->duplex = ecmd.duplex; -+ goto send_event; -+ } -+ } -+ port->speed = 0; -+ port->duplex = 0; -+ -+send_event: -+ err = team_nl_send_event_port_list_get(port); -+ if (err) -+ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", -+ port->dev->name); -+ -+} -+ -+static void team_port_change_check(struct team_port *port, bool linkup) -+{ -+ struct team *team = port->team; -+ -+ spin_lock(&team->lock); -+ __team_port_change_check(port, linkup); -+ spin_unlock(&team->lock); -+} -+ -+/************************************ -+ * Net device notifier event handler -+ ************************************/ -+ -+static int team_device_event(struct notifier_block *unused, -+ unsigned long event, void *ptr) -+{ -+ struct net_device *dev = (struct net_device *) ptr; -+ struct team_port *port; -+ -+ port = team_port_get_rtnl(dev); -+ if (!port) -+ return NOTIFY_DONE; -+ -+ switch (event) { -+ case NETDEV_UP: -+ if (netif_carrier_ok(dev)) -+ team_port_change_check(port, true); -+ case NETDEV_DOWN: -+ team_port_change_check(port, false); -+ case NETDEV_CHANGE: -+ if (netif_running(port->dev)) -+ team_port_change_check(port, -+ !!netif_carrier_ok(port->dev)); -+ break; -+ case NETDEV_UNREGISTER: -+ team_del_slave(port->team->dev, dev); -+ break; -+ case NETDEV_FEAT_CHANGE: -+ team_compute_features(port->team); -+ break; -+ case NETDEV_CHANGEMTU: -+ /* Forbid to change mtu of underlaying device */ -+ return NOTIFY_BAD; -+ case NETDEV_PRE_TYPE_CHANGE: -+ /* Forbid to change type of underlaying device */ -+ return NOTIFY_BAD; -+ } -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block team_notifier_block __read_mostly = { -+ .notifier_call = team_device_event, -+}; -+ -+ -+/*********************** -+ * Module init and exit -+ ***********************/ -+ -+static int __init team_module_init(void) -+{ -+ int err; -+ -+ register_netdevice_notifier(&team_notifier_block); -+ -+ err = rtnl_link_register(&team_link_ops); -+ if (err) -+ goto err_rtnl_reg; -+ -+ err = team_nl_init(); -+ if (err) -+ goto err_nl_init; -+ -+ return 0; -+ -+err_nl_init: -+ rtnl_link_unregister(&team_link_ops); -+ -+err_rtnl_reg: -+ unregister_netdevice_notifier(&team_notifier_block); -+ -+ return err; -+} -+ -+static void __exit team_module_exit(void) -+{ -+ team_nl_fini(); -+ rtnl_link_unregister(&team_link_ops); -+ unregister_netdevice_notifier(&team_notifier_block); -+} -+ -+module_init(team_module_init); -+module_exit(team_module_exit); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Jiri Pirko "); -+MODULE_DESCRIPTION("Ethernet team device driver"); -+MODULE_ALIAS_RTNL_LINK(DRV_NAME); -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -new file mode 100644 -index 0000000..6fe920c ---- /dev/null -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -0,0 +1,137 @@ -+/* -+ * net/drivers/team/team_mode_activebackup.c - Active-backup mode for team -+ * Copyright (c) 2011 Jiri Pirko -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ab_priv { -+ struct team_port __rcu *active_port; -+}; -+ -+static struct ab_priv *ab_priv(struct team *team) -+{ -+ return (struct ab_priv *) &team->mode_priv; -+} -+ -+static rx_handler_result_t ab_receive(struct team *team, struct team_port *port, -+ struct sk_buff *skb) { -+ struct team_port *active_port; -+ -+ active_port = rcu_dereference(ab_priv(team)->active_port); -+ if (active_port != port) -+ return RX_HANDLER_EXACT; -+ return RX_HANDLER_ANOTHER; -+} -+ -+static bool ab_transmit(struct team *team, struct sk_buff *skb) -+{ -+ struct team_port *active_port; -+ -+ active_port = rcu_dereference(ab_priv(team)->active_port); -+ if (unlikely(!active_port)) -+ goto drop; -+ skb->dev = active_port->dev; -+ if (dev_queue_xmit(skb)) -+ return false; -+ return true; -+ -+drop: -+ dev_kfree_skb_any(skb); -+ return false; -+} -+ -+static void ab_port_leave(struct team *team, struct team_port *port) -+{ -+ if (ab_priv(team)->active_port == port) -+ rcu_assign_pointer(ab_priv(team)->active_port, NULL); -+} -+ -+static int ab_active_port_get(struct team *team, void *arg) -+{ -+ u32 *ifindex = arg; -+ -+ *ifindex = 0; -+ if (ab_priv(team)->active_port) -+ *ifindex = ab_priv(team)->active_port->dev->ifindex; -+ return 0; -+} -+ -+static int ab_active_port_set(struct team *team, void *arg) -+{ -+ u32 *ifindex = arg; -+ struct team_port *port; -+ -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ if (port->dev->ifindex == *ifindex) { -+ rcu_assign_pointer(ab_priv(team)->active_port, port); -+ return 0; -+ } -+ } -+ return -ENOENT; -+} -+ -+static struct team_option ab_options[] = { -+ { -+ .name = "activeport", -+ .type = TEAM_OPTION_TYPE_U32, -+ .getter = ab_active_port_get, -+ .setter = ab_active_port_set, -+ }, -+}; -+ -+int ab_init(struct team *team) -+{ -+ team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); -+ return 0; -+} -+ -+void ab_exit(struct team *team) -+{ -+ team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options)); -+} -+ -+static const struct team_mode_ops ab_mode_ops = { -+ .init = ab_init, -+ .exit = ab_exit, -+ .receive = ab_receive, -+ .transmit = ab_transmit, -+ .port_leave = ab_port_leave, -+}; -+ -+static struct team_mode ab_mode = { -+ .kind = "activebackup", -+ .owner = THIS_MODULE, -+ .priv_size = sizeof(struct ab_priv), -+ .ops = &ab_mode_ops, -+}; -+ -+static int __init ab_init_module(void) -+{ -+ return team_mode_register(&ab_mode); -+} -+ -+static void __exit ab_cleanup_module(void) -+{ -+ team_mode_unregister(&ab_mode); -+} -+ -+module_init(ab_init_module); -+module_exit(ab_cleanup_module); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Jiri Pirko "); -+MODULE_DESCRIPTION("Active-backup mode for team"); -+MODULE_ALIAS("team-mode-activebackup"); -diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c -new file mode 100644 -index 0000000..a0e8f80 ---- /dev/null -+++ b/drivers/net/team/team_mode_roundrobin.c -@@ -0,0 +1,107 @@ -+/* -+ * net/drivers/team/team_mode_roundrobin.c - Round-robin mode for team -+ * Copyright (c) 2011 Jiri Pirko -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rr_priv { -+ unsigned int sent_packets; -+}; -+ -+static struct rr_priv *rr_priv(struct team *team) -+{ -+ return (struct rr_priv *) &team->mode_priv; -+} -+ -+static struct team_port *__get_first_port_up(struct team *team, -+ struct team_port *port) -+{ -+ struct team_port *cur; -+ -+ if (port->linkup) -+ return port; -+ cur = port; -+ list_for_each_entry_continue_rcu(cur, &team->port_list, list) -+ if (cur->linkup) -+ return cur; -+ list_for_each_entry_rcu(cur, &team->port_list, list) { -+ if (cur == port) -+ break; -+ if (cur->linkup) -+ return cur; -+ } -+ return NULL; -+} -+ -+static bool rr_transmit(struct team *team, struct sk_buff *skb) -+{ -+ struct team_port *port; -+ int port_index; -+ -+ port_index = rr_priv(team)->sent_packets++ % team->port_count; -+ port = team_get_port_by_index_rcu(team, port_index); -+ port = __get_first_port_up(team, port); -+ if (unlikely(!port)) -+ goto drop; -+ skb->dev = port->dev; -+ if (dev_queue_xmit(skb)) -+ return false; -+ return true; -+ -+drop: -+ dev_kfree_skb_any(skb); -+ return false; -+} -+ -+static int rr_port_enter(struct team *team, struct team_port *port) -+{ -+ return team_port_set_team_mac(port); -+} -+ -+static void rr_port_change_mac(struct team *team, struct team_port *port) -+{ -+ team_port_set_team_mac(port); -+} -+ -+static const struct team_mode_ops rr_mode_ops = { -+ .transmit = rr_transmit, -+ .port_enter = rr_port_enter, -+ .port_change_mac = rr_port_change_mac, -+}; -+ -+static struct team_mode rr_mode = { -+ .kind = "roundrobin", -+ .owner = THIS_MODULE, -+ .priv_size = sizeof(struct rr_priv), -+ .ops = &rr_mode_ops, -+}; -+ -+static int __init rr_init_module(void) -+{ -+ return team_mode_register(&rr_mode); -+} -+ -+static void __exit rr_cleanup_module(void) -+{ -+ team_mode_unregister(&rr_mode); -+} -+ -+module_init(rr_init_module); -+module_exit(rr_cleanup_module); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Jiri Pirko "); -+MODULE_DESCRIPTION("Round-robin mode for team"); -+MODULE_ALIAS("team-mode-roundrobin"); -diff --git a/include/linux/Kbuild b/include/linux/Kbuild -index 619b565..0b091b3 100644 ---- a/include/linux/Kbuild -+++ b/include/linux/Kbuild -@@ -185,6 +185,7 @@ header-y += if_pppol2tp.h - header-y += if_pppox.h - header-y += if_slip.h - header-y += if_strip.h -+header-y += if_team.h - header-y += if_tr.h - header-y += if_tun.h - header-y += if_tunnel.h -diff --git a/include/linux/if.h b/include/linux/if.h -index db20bd4..06b6ef6 100644 ---- a/include/linux/if.h -+++ b/include/linux/if.h -@@ -79,6 +79,7 @@ - #define IFF_TX_SKB_SHARING 0x10000 /* The interface supports sharing - * skbs on transmit */ - #define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ -+#define IFF_TEAM_PORT 0x40000 /* device used as team port */ - - #define IF_GET_IFACE 0x0001 /* for querying only */ - #define IF_GET_PROTO 0x0002 -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -new file mode 100644 -index 0000000..14f6388 ---- /dev/null -+++ b/include/linux/if_team.h -@@ -0,0 +1,242 @@ -+/* -+ * include/linux/if_team.h - Network team device driver header -+ * Copyright (c) 2011 Jiri Pirko -+ * -+ * 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. -+ */ -+ -+#ifndef _LINUX_IF_TEAM_H_ -+#define _LINUX_IF_TEAM_H_ -+ -+#ifdef __KERNEL__ -+ -+struct team_pcpu_stats { -+ u64 rx_packets; -+ u64 rx_bytes; -+ u64 rx_multicast; -+ u64 tx_packets; -+ u64 tx_bytes; -+ struct u64_stats_sync syncp; -+ u32 rx_dropped; -+ u32 tx_dropped; -+}; -+ -+struct team; -+ -+struct team_port { -+ struct net_device *dev; -+ struct hlist_node hlist; /* node in hash list */ -+ struct list_head list; /* node in ordinary list */ -+ struct team *team; -+ int index; -+ -+ /* -+ * A place for storing original values of the device before it -+ * become a port. -+ */ -+ struct { -+ unsigned char dev_addr[MAX_ADDR_LEN]; -+ unsigned int mtu; -+ } orig; -+ -+ bool linkup; -+ u32 speed; -+ u8 duplex; -+ -+ struct rcu_head rcu; -+}; -+ -+struct team_mode_ops { -+ int (*init)(struct team *team); -+ void (*exit)(struct team *team); -+ rx_handler_result_t (*receive)(struct team *team, -+ struct team_port *port, -+ struct sk_buff *skb); -+ bool (*transmit)(struct team *team, struct sk_buff *skb); -+ int (*port_enter)(struct team *team, struct team_port *port); -+ void (*port_leave)(struct team *team, struct team_port *port); -+ void (*port_change_mac)(struct team *team, struct team_port *port); -+}; -+ -+enum team_option_type { -+ TEAM_OPTION_TYPE_U32, -+ TEAM_OPTION_TYPE_STRING, -+}; -+ -+struct team_option { -+ struct list_head list; -+ const char *name; -+ enum team_option_type type; -+ int (*getter)(struct team *team, void *arg); -+ int (*setter)(struct team *team, void *arg); -+}; -+ -+struct team_mode { -+ struct list_head list; -+ const char *kind; -+ struct module *owner; -+ size_t priv_size; -+ const struct team_mode_ops *ops; -+}; -+ -+#define TEAM_PORT_HASHBITS 4 -+#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS) -+ -+#define TEAM_MODE_PRIV_LONGS 4 -+#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS) -+ -+struct team { -+ struct net_device *dev; /* associated netdevice */ -+ struct team_pcpu_stats __percpu *pcpu_stats; -+ -+ spinlock_t lock; /* used for overall locking, e.g. port lists write */ -+ -+ /* -+ * port lists with port count -+ */ -+ int port_count; -+ struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES]; -+ struct list_head port_list; -+ -+ struct list_head option_list; -+ -+ const struct team_mode *mode; -+ struct team_mode_ops ops; -+ long mode_priv[TEAM_MODE_PRIV_LONGS]; -+}; -+ -+static inline struct hlist_head *team_port_index_hash(struct team *team, -+ int port_index) -+{ -+ return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; -+} -+ -+static inline struct team_port *team_get_port_by_index(struct team *team, -+ int port_index) -+{ -+ struct hlist_node *p; -+ struct team_port *port; -+ struct hlist_head *head = team_port_index_hash(team, port_index); -+ -+ hlist_for_each_entry(port, p, head, hlist) -+ if (port->index == port_index) -+ return port; -+ return NULL; -+} -+static inline struct team_port *team_get_port_by_index_rcu(struct team *team, -+ int port_index) -+{ -+ struct hlist_node *p; -+ struct team_port *port; -+ struct hlist_head *head = team_port_index_hash(team, port_index); -+ -+ hlist_for_each_entry_rcu(port, p, head, hlist) -+ if (port->index == port_index) -+ return port; -+ return NULL; -+} -+ -+extern int team_port_set_team_mac(struct team_port *port); -+extern void team_options_register(struct team *team, -+ struct team_option *option, -+ size_t option_count); -+extern void team_options_unregister(struct team *team, -+ struct team_option *option, -+ size_t option_count); -+extern int team_mode_register(struct team_mode *mode); -+extern int team_mode_unregister(struct team_mode *mode); -+ -+#endif /* __KERNEL__ */ -+ -+#define TEAM_STRING_MAX_LEN 32 -+ -+/********************************** -+ * NETLINK_GENERIC netlink family. -+ **********************************/ -+ -+enum { -+ TEAM_CMD_NOOP, -+ TEAM_CMD_OPTIONS_SET, -+ TEAM_CMD_OPTIONS_GET, -+ TEAM_CMD_PORT_LIST_GET, -+ -+ __TEAM_CMD_MAX, -+ TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1), -+}; -+ -+enum { -+ TEAM_ATTR_UNSPEC, -+ TEAM_ATTR_TEAM_IFINDEX, /* u32 */ -+ TEAM_ATTR_LIST_OPTION, /* nest */ -+ TEAM_ATTR_LIST_PORT, /* nest */ -+ -+ __TEAM_ATTR_MAX, -+ TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1, -+}; -+ -+/* Nested layout of get/set msg: -+ * -+ * [TEAM_ATTR_LIST_OPTION] -+ * [TEAM_ATTR_ITEM_OPTION] -+ * [TEAM_ATTR_OPTION_*], ... -+ * [TEAM_ATTR_ITEM_OPTION] -+ * [TEAM_ATTR_OPTION_*], ... -+ * ... -+ * [TEAM_ATTR_LIST_PORT] -+ * [TEAM_ATTR_ITEM_PORT] -+ * [TEAM_ATTR_PORT_*], ... -+ * [TEAM_ATTR_ITEM_PORT] -+ * [TEAM_ATTR_PORT_*], ... -+ * ... -+ */ -+ -+enum { -+ TEAM_ATTR_ITEM_OPTION_UNSPEC, -+ TEAM_ATTR_ITEM_OPTION, /* nest */ -+ -+ __TEAM_ATTR_ITEM_OPTION_MAX, -+ TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1, -+}; -+ -+enum { -+ TEAM_ATTR_OPTION_UNSPEC, -+ TEAM_ATTR_OPTION_NAME, /* string */ -+ TEAM_ATTR_OPTION_CHANGED, /* flag */ -+ TEAM_ATTR_OPTION_TYPE, /* u8 */ -+ TEAM_ATTR_OPTION_DATA, /* dynamic */ -+ -+ __TEAM_ATTR_OPTION_MAX, -+ TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, -+}; -+ -+enum { -+ TEAM_ATTR_ITEM_PORT_UNSPEC, -+ TEAM_ATTR_ITEM_PORT, /* nest */ -+ -+ __TEAM_ATTR_ITEM_PORT_MAX, -+ TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1, -+}; -+ -+enum { -+ TEAM_ATTR_PORT_UNSPEC, -+ TEAM_ATTR_PORT_IFINDEX, /* u32 */ -+ TEAM_ATTR_PORT_CHANGED, /* flag */ -+ TEAM_ATTR_PORT_LINKUP, /* flag */ -+ TEAM_ATTR_PORT_SPEED, /* u32 */ -+ TEAM_ATTR_PORT_DUPLEX, /* u8 */ -+ -+ __TEAM_ATTR_PORT_MAX, -+ TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, -+}; -+ -+/* -+ * NETLINK_GENERIC related info -+ */ -+#define TEAM_GENL_NAME "team" -+#define TEAM_GENL_VERSION 0x1 -+#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event" -+ -+#endif /* _LINUX_IF_TEAM_H_ */ diff --git a/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch b/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch deleted file mode 100644 index 3aea3caeb..000000000 --- a/debian/patches/features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Jiri Pirko -Date: Wed, 16 Nov 2011 11:55:54 +0000 -Subject: [02/23] team: Do not hold rcu_read_lock when running netlink cmds - -commit 8c0713a57482ebfadef197c856a38af3a55444c6 upstream. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 60672bb..e5390c7 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1043,8 +1043,7 @@ err_msg_put: - - /* - * Netlink cmd functions should be locked by following two functions. -- * To ensure team_uninit would not be called in between, hold rcu_read_lock -- * all the time. -+ * Since dev gets held here, that ensures dev won't disappear in between. - */ - static struct team *team_nl_team_get(struct genl_info *info) - { -@@ -1057,10 +1056,10 @@ static struct team *team_nl_team_get(struct genl_info *info) - return NULL; - - ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]); -- rcu_read_lock(); -- dev = dev_get_by_index_rcu(net, ifindex); -+ dev = dev_get_by_index(net, ifindex); - if (!dev || dev->netdev_ops != &team_netdev_ops) { -- rcu_read_unlock(); -+ if (dev) -+ dev_put(dev); - return NULL; - } - -@@ -1072,7 +1071,7 @@ static struct team *team_nl_team_get(struct genl_info *info) - static void team_nl_team_put(struct team *team) - { - spin_unlock(&team->lock); -- rcu_read_unlock(); -+ dev_put(team->dev); - } - - static int team_nl_send_generic(struct genl_info *info, struct team *team, diff --git a/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch b/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch deleted file mode 100644 index 67f740f4f..000000000 --- a/debian/patches/features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch +++ /dev/null @@ -1,149 +0,0 @@ -From: Jiri Pirko -Date: Wed, 16 Nov 2011 11:09:08 +0000 -Subject: [03/23] team: convert overall spinlock to mutex - -commit 61dc3461b9549bc10a2f16d254250680cadafcce upstream. - -No need to have spinlock for this purpose. So convert this to mutex and -avoid current schedule while atomic problems in netlink code. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 32 ++++++++++++++++---------------- - include/linux/if_team.h | 2 +- - 2 files changed, 17 insertions(+), 17 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index e5390c7..7db219c 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -443,9 +443,9 @@ static void __team_compute_features(struct team *team) - - static void team_compute_features(struct team *team) - { -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - __team_compute_features(team); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - } - - static int team_port_enter(struct team *team, struct team_port *port) -@@ -647,7 +647,7 @@ static int team_init(struct net_device *dev) - int i; - - team->dev = dev; -- spin_lock_init(&team->lock); -+ mutex_init(&team->lock); - - team->pcpu_stats = alloc_percpu(struct team_pcpu_stats); - if (!team->pcpu_stats) -@@ -672,13 +672,13 @@ static void team_uninit(struct net_device *dev) - struct team_port *port; - struct team_port *tmp; - -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - list_for_each_entry_safe(port, tmp, &team->port_list, list) - team_port_del(team, port->dev); - - __team_change_mode(team, NULL); /* cleanup */ - __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - } - - static void team_destructor(struct net_device *dev) -@@ -784,7 +784,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) - * Alhough this is reader, it's guarded by team lock. It's not possible - * to traverse list in reverse under rcu_read_lock - */ -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - list_for_each_entry(port, &team->port_list, list) { - err = dev_set_mtu(port->dev, new_mtu); - if (err) { -@@ -793,7 +793,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) - goto unwind; - } - } -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - - dev->mtu = new_mtu; - -@@ -802,7 +802,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu) - unwind: - list_for_each_entry_continue_reverse(port, &team->port_list, list) - dev_set_mtu(port->dev, dev->mtu); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - - return err; - } -@@ -880,9 +880,9 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev) - struct team *team = netdev_priv(dev); - int err; - -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - err = team_port_add(team, port_dev); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - return err; - } - -@@ -891,9 +891,9 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) - struct team *team = netdev_priv(dev); - int err; - -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - err = team_port_del(team, port_dev); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - return err; - } - -@@ -1064,13 +1064,13 @@ static struct team *team_nl_team_get(struct genl_info *info) - } - - team = netdev_priv(dev); -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - return team; - } - - static void team_nl_team_put(struct team *team) - { -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - dev_put(team->dev); - } - -@@ -1486,9 +1486,9 @@ static void team_port_change_check(struct team_port *port, bool linkup) - { - struct team *team = port->team; - -- spin_lock(&team->lock); -+ mutex_lock(&team->lock); - __team_port_change_check(port, linkup); -- spin_unlock(&team->lock); -+ mutex_unlock(&team->lock); - } - - /************************************ -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 14f6388..a6eac12 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -92,7 +92,7 @@ struct team { - struct net_device *dev; /* associated netdevice */ - struct team_pcpu_stats __percpu *pcpu_stats; - -- spinlock_t lock; /* used for overall locking, e.g. port lists write */ -+ struct mutex lock; /* used for overall locking, e.g. port lists write */ - - /* - * port lists with port count diff --git a/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch b/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch deleted file mode 100644 index 24b65c675..000000000 --- a/debian/patches/features/all/team/0004-team-replicate-options-on-register.patch +++ /dev/null @@ -1,189 +0,0 @@ -From: Jiri Pirko -Date: Wed, 16 Nov 2011 11:09:09 +0000 -Subject: [04/23] team: replicate options on register - -commit 358b838291f618278080bbed435b755f9b46748e upstream. - -Since multiple team instances are putting defined options into their -option list, during register each option must be cloned before added -into list. This resolves uncool memory corruptions when using multiple -teams. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 76 +++++++++++++++++++++++++---- - drivers/net/team/team_mode_activebackup.c | 5 +- - include/linux/if_team.h | 8 +-- - 3 files changed, 72 insertions(+), 17 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 7db219c..f309274 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -80,30 +80,78 @@ EXPORT_SYMBOL(team_port_set_team_mac); - * Options handling - *******************/ - --void team_options_register(struct team *team, struct team_option *option, -- size_t option_count) -+struct team_option *__team_find_option(struct team *team, const char *opt_name) -+{ -+ struct team_option *option; -+ -+ list_for_each_entry(option, &team->option_list, list) { -+ if (strcmp(option->name, opt_name) == 0) -+ return option; -+ } -+ return NULL; -+} -+ -+int team_options_register(struct team *team, -+ const struct team_option *option, -+ size_t option_count) - { - int i; -+ struct team_option *dst_opts[option_count]; -+ int err; -+ -+ memset(dst_opts, 0, sizeof(dst_opts)); -+ for (i = 0; i < option_count; i++, option++) { -+ struct team_option *dst_opt; -+ -+ if (__team_find_option(team, option->name)) { -+ err = -EEXIST; -+ goto rollback; -+ } -+ dst_opt = kmalloc(sizeof(*option), GFP_KERNEL); -+ if (!dst_opt) { -+ err = -ENOMEM; -+ goto rollback; -+ } -+ memcpy(dst_opt, option, sizeof(*option)); -+ dst_opts[i] = dst_opt; -+ } -+ -+ for (i = 0; i < option_count; i++) -+ list_add_tail(&dst_opts[i]->list, &team->option_list); - -- for (i = 0; i < option_count; i++, option++) -- list_add_tail(&option->list, &team->option_list); -+ return 0; -+ -+rollback: -+ for (i = 0; i < option_count; i++) -+ kfree(dst_opts[i]); -+ -+ return err; - } -+ - EXPORT_SYMBOL(team_options_register); - - static void __team_options_change_check(struct team *team, - struct team_option *changed_option); - - static void __team_options_unregister(struct team *team, -- struct team_option *option, -+ const struct team_option *option, - size_t option_count) - { - int i; - -- for (i = 0; i < option_count; i++, option++) -- list_del(&option->list); -+ for (i = 0; i < option_count; i++, option++) { -+ struct team_option *del_opt; -+ -+ del_opt = __team_find_option(team, option->name); -+ if (del_opt) { -+ list_del(&del_opt->list); -+ kfree(del_opt); -+ } -+ } - } - --void team_options_unregister(struct team *team, struct team_option *option, -+void team_options_unregister(struct team *team, -+ const struct team_option *option, - size_t option_count) - { - __team_options_unregister(team, option, option_count); -@@ -632,7 +680,7 @@ static int team_mode_option_set(struct team *team, void *arg) - return team_change_mode(team, *str); - } - --static struct team_option team_options[] = { -+static const struct team_option team_options[] = { - { - .name = "mode", - .type = TEAM_OPTION_TYPE_STRING, -@@ -645,6 +693,7 @@ static int team_init(struct net_device *dev) - { - struct team *team = netdev_priv(dev); - int i; -+ int err; - - team->dev = dev; - mutex_init(&team->lock); -@@ -660,10 +709,17 @@ static int team_init(struct net_device *dev) - team_adjust_ops(team); - - INIT_LIST_HEAD(&team->option_list); -- team_options_register(team, team_options, ARRAY_SIZE(team_options)); -+ err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); -+ if (err) -+ goto err_options_register; - netif_carrier_off(dev); - - return 0; -+ -+err_options_register: -+ free_percpu(team->pcpu_stats); -+ -+ return err; - } - - static void team_uninit(struct net_device *dev) -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -index 6fe920c..b344275 100644 ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -83,7 +83,7 @@ static int ab_active_port_set(struct team *team, void *arg) - return -ENOENT; - } - --static struct team_option ab_options[] = { -+static const struct team_option ab_options[] = { - { - .name = "activeport", - .type = TEAM_OPTION_TYPE_U32, -@@ -94,8 +94,7 @@ static struct team_option ab_options[] = { - - int ab_init(struct team *team) - { -- team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); -- return 0; -+ return team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); - } - - void ab_exit(struct team *team) -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index a6eac12..828181f 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -140,11 +140,11 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team, - } - - extern int team_port_set_team_mac(struct team_port *port); --extern void team_options_register(struct team *team, -- struct team_option *option, -- size_t option_count); -+extern int team_options_register(struct team *team, -+ const struct team_option *option, -+ size_t option_count); - extern void team_options_unregister(struct team *team, -- struct team_option *option, -+ const struct team_option *option, - size_t option_count); - extern int team_mode_register(struct team_mode *mode); - extern int team_mode_unregister(struct team_mode *mode); diff --git a/debian/patches/features/all/team/0005-team-add-fix_features.patch b/debian/patches/features/all/team/0005-team-add-fix_features.patch deleted file mode 100644 index 85a504ce5..000000000 --- a/debian/patches/features/all/team/0005-team-add-fix_features.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Jiri Pirko -Date: Thu, 17 Nov 2011 04:16:04 +0000 -Subject: [05/23] team: add fix_features - -commit 234a8fd49d086f5a3debb379bfdf4e6b51f0c0e2 upstream. - -do fix features in similar way as bonding code does - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index f309274..5b169c1 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -953,6 +953,27 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) - return err; - } - -+static netdev_features_t team_fix_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ struct team_port *port; -+ struct team *team = netdev_priv(dev); -+ netdev_features_t mask; -+ -+ mask = features; -+ features &= ~NETIF_F_ONE_FOR_ALL; -+ features |= NETIF_F_ALL_FOR_ALL; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(port, &team->port_list, list) { -+ features = netdev_increment_features(features, -+ port->dev->features, -+ mask); -+ } -+ rcu_read_unlock(); -+ return features; -+} -+ - static const struct net_device_ops team_netdev_ops = { - .ndo_init = team_init, - .ndo_uninit = team_uninit, -@@ -968,6 +989,7 @@ static const struct net_device_ops team_netdev_ops = { - .ndo_vlan_rx_kill_vid = team_vlan_rx_kill_vid, - .ndo_add_slave = team_add_slave, - .ndo_del_slave = team_del_slave, -+ .ndo_fix_features = team_fix_features, - }; - - diff --git a/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch b/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch deleted file mode 100644 index 2abd0fe1c..000000000 --- a/debian/patches/features/all/team/0006-team-avoid-using-variable-length-array.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Jiri Pirko -Date: Thu, 17 Nov 2011 04:16:05 +0000 -Subject: [06/23] team: avoid using variable-length array - -commit 2bba19fff8d09bf19df5d5e2de7188d65de67c3e upstream. - -Apparently using variable-length array is not correct -(https://lkml.org/lkml/2011/10/23/25). So remove it. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 5b169c1..c48ef19 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -96,10 +96,13 @@ int team_options_register(struct team *team, - size_t option_count) - { - int i; -- struct team_option *dst_opts[option_count]; -+ struct team_option **dst_opts; - int err; - -- memset(dst_opts, 0, sizeof(dst_opts)); -+ dst_opts = kzalloc(sizeof(struct team_option *) * option_count, -+ GFP_KERNEL); -+ if (!dst_opts) -+ return -ENOMEM; - for (i = 0; i < option_count; i++, option++) { - struct team_option *dst_opt; - -@@ -119,12 +122,14 @@ int team_options_register(struct team *team, - for (i = 0; i < option_count; i++) - list_add_tail(&dst_opts[i]->list, &team->option_list); - -+ kfree(dst_opts); - return 0; - - rollback: - for (i = 0; i < option_count; i++) - kfree(dst_opts[i]); - -+ kfree(dst_opts); - return err; - } - diff --git a/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch b/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch deleted file mode 100644 index 7680fbdfd..000000000 --- a/debian/patches/features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Jiri Pirko -Date: Thu, 17 Nov 2011 06:32:37 +0000 -Subject: [07/23] team: replace kmalloc+memcpy by kmemdup - -commit f8a15af093b19b86d56933c8757cee298d0f32a8 upstream. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index c48ef19..064155d 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -104,19 +104,15 @@ int team_options_register(struct team *team, - if (!dst_opts) - return -ENOMEM; - for (i = 0; i < option_count; i++, option++) { -- struct team_option *dst_opt; -- - if (__team_find_option(team, option->name)) { - err = -EEXIST; - goto rollback; - } -- dst_opt = kmalloc(sizeof(*option), GFP_KERNEL); -- if (!dst_opt) { -+ dst_opts[i] = kmemdup(option, sizeof(*option), GFP_KERNEL); -+ if (!dst_opts[i]) { - err = -ENOMEM; - goto rollback; - } -- memcpy(dst_opt, option, sizeof(*option)); -- dst_opts[i] = dst_opt; - } - - for (i = 0; i < option_count; i++) diff --git a/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch b/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch deleted file mode 100644 index 9bd5f39de..000000000 --- a/debian/patches/features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Eric Dumazet -Date: Wed, 23 Nov 2011 07:09:32 +0000 -Subject: [08/23] net: treewide use of RCU_INIT_POINTER - -commit 2cfa5a0471fef43fda0b7bd87e3a5e4dbadb7809 upstream. - -rcu_assign_pointer(ptr, NULL) can be safely replaced by -RCU_INIT_POINTER(ptr, NULL) - -(old rcu_assign_pointer() macro was testing the NULL value and could -omit the smp_wmb(), but this had to be removed because of compiler -warnings) - -Signed-off-by: Eric Dumazet -Signed-off-by: David S. Miller -[bwh: Restrict to drivers/net/team/] ---- ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -56,7 +56,7 @@ drop: - static void ab_port_leave(struct team *team, struct team_port *port) - { - if (ab_priv(team)->active_port == port) -- rcu_assign_pointer(ab_priv(team)->active_port, NULL); -+ RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); - } - - static int ab_active_port_get(struct team *team, void *arg) diff --git a/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch b/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch deleted file mode 100644 index f30b01ec2..000000000 --- a/debian/patches/features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch +++ /dev/null @@ -1,132 +0,0 @@ -From: Jiri Pirko -Date: Thu, 8 Dec 2011 04:11:17 +0000 -Subject: [09/23] net: introduce vlan_vid_[add/del] and use them instead of - direct [add/kill]_vid ndo calls - -commit 87002b03baabd2b8f6281ab6411ed88d24958de1 upstream. - -This patch adds wrapper for ndo_vlan_rx_add_vid/ndo_vlan_rx_kill_vid -functions. Check for NETIF_F_HW_VLAN_FILTER feature is done in this -wrapper. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller -[bwh: Drop changes to bonding, macvlan, vlan; assume - ndo_vlan_rx_{add,kill}_vid still return void] ---- ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -906,15 +907,26 @@ - { - struct team *team = netdev_priv(dev); - struct team_port *port; -+ int err; - -- rcu_read_lock(); -- list_for_each_entry_rcu(port, &team->port_list, list) { -- const struct net_device_ops *ops = port->dev->netdev_ops; -- -- if (ops->ndo_vlan_rx_add_vid) -- ops->ndo_vlan_rx_add_vid(port->dev, vid); -+ /* -+ * Alhough this is reader, it's guarded by team lock. It's not possible -+ * to traverse list in reverse under rcu_read_lock -+ */ -+ mutex_lock(&team->lock); -+ list_for_each_entry(port, &team->port_list, list) { -+ err = vlan_vid_add(port->dev, vid); -+ if (err) -+ goto unwind; - } -- rcu_read_unlock(); -+ mutex_unlock(&team->lock); -+ -+ return; -+ -+unwind: -+ list_for_each_entry_continue_reverse(port, &team->port_list, list) -+ vlan_vid_del(port->dev, vid); -+ mutex_unlock(&team->lock); - } - - static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -@@ -923,12 +935,8 @@ - struct team_port *port; - - rcu_read_lock(); -- list_for_each_entry_rcu(port, &team->port_list, list) { -- const struct net_device_ops *ops = port->dev->netdev_ops; -- -- if (ops->ndo_vlan_rx_kill_vid) -- ops->ndo_vlan_rx_kill_vid(port->dev, vid); -- } -+ list_for_each_entry_rcu(port, &team->port_list, list) -+ vlan_vid_del(port->dev, vid); - rcu_read_unlock(); - } - ---- a/include/linux/if_vlan.h -+++ b/include/linux/if_vlan.h -@@ -109,6 +109,9 @@ - extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); - extern struct sk_buff *vlan_untag(struct sk_buff *skb); - -+extern int vlan_vid_add(struct net_device *dev, unsigned short vid); -+extern void vlan_vid_del(struct net_device *dev, unsigned short vid); -+ - #else - static inline struct net_device * - __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) -@@ -139,6 +142,15 @@ - { - return skb; - } -+ -+static inline int vlan_vid_add(struct net_device *dev, unsigned short vid) -+{ -+ return 0; -+} -+ -+static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) -+{ -+} - #endif - - /** ---- a/net/8021q/vlan_core.c -+++ b/net/8021q/vlan_core.c -@@ -179,3 +179,26 @@ - kfree_skb(skb); - return NULL; - } -+ -+int vlan_vid_add(struct net_device *dev, unsigned short vid) -+{ -+ const struct net_device_ops *ops = dev->netdev_ops; -+ -+ if ((dev->features & NETIF_F_HW_VLAN_FILTER) && -+ ops->ndo_vlan_rx_add_vid) { -+ ops->ndo_vlan_rx_add_vid(dev, vid); -+ } -+ return 0; -+} -+EXPORT_SYMBOL(vlan_vid_add); -+ -+void vlan_vid_del(struct net_device *dev, unsigned short vid) -+{ -+ const struct net_device_ops *ops = dev->netdev_ops; -+ -+ if ((dev->features & NETIF_F_HW_VLAN_FILTER) && -+ ops->ndo_vlan_rx_kill_vid) { -+ ops->ndo_vlan_rx_kill_vid(dev, vid); -+ } -+} -+EXPORT_SYMBOL(vlan_vid_del); diff --git a/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch b/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch deleted file mode 100644 index f6ebb7e8c..000000000 --- a/debian/patches/features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch +++ /dev/null @@ -1,81 +0,0 @@ -From: Jiri Pirko -Date: Thu, 8 Dec 2011 04:11:19 +0000 -Subject: [10/23] vlan: introduce functions to do mass addition/deletion of vids by - another device - -commit 348a1443cc4303c72cf1ee3b26e476fec8e7b5fa upstream. - -Introduce functions handy to copy vlan ids from one driver's list to -another. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller -[bwh: Assume ndo_vlan_rx_add_id still returns void] ---- ---- a/include/linux/if_vlan.h -+++ b/include/linux/if_vlan.h -@@ -112,6 +112,10 @@ - extern int vlan_vid_add(struct net_device *dev, unsigned short vid); - extern void vlan_vid_del(struct net_device *dev, unsigned short vid); - -+extern int vlan_vids_add_by_dev(struct net_device *dev, -+ const struct net_device *by_dev); -+extern void vlan_vids_del_by_dev(struct net_device *dev, -+ const struct net_device *by_dev); - #else - static inline struct net_device * - __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) -@@ -151,6 +155,16 @@ - static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) - { - } -+ -+static inline int vlan_vids_add_by_dev(struct net_device *dev, -+ const struct net_device *by_dev) -+{ -+} -+ -+static inline void vlan_vids_del_by_dev(struct net_device *dev, -+ const struct net_device *by_dev) -+{ -+} - #endif - - /** ---- a/net/8021q/vlan_core.c -+++ b/net/8021q/vlan_core.c -@@ -202,3 +202,34 @@ - } - } - EXPORT_SYMBOL(vlan_vid_del); -+ -+int vlan_vids_add_by_dev(struct net_device *dev, -+ const struct net_device *by_dev) -+{ -+ struct vlan_vid_info *vid_info; -+ -+ ASSERT_RTNL(); -+ -+ if (!by_dev->vlan_info) -+ return; -+ -+ list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) { -+ vlan_vid_add(dev, vid_info->vid); -+ } -+ return 0; -+} -+EXPORT_SYMBOL(vlan_vids_add_by_dev); -+ -+void vlan_vids_del_by_dev(struct net_device *dev, -+ const struct net_device *by_dev) -+{ -+ struct vlan_vid_info *vid_info; -+ -+ ASSERT_RTNL(); -+ -+ if (!by_dev->vlan_info) -+ return; -+ -+ list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) -+ vlan_vid_del(dev, vid_info->vid); -+} diff --git a/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch b/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch deleted file mode 100644 index 9cbbde450..000000000 --- a/debian/patches/features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Jiri Pirko -Date: Thu, 8 Dec 2011 04:11:20 +0000 -Subject: [11/23] team: use vlan_vids_[addr/del]_by_dev - -commit 57459185a19b0246866479522b77cbb9732201d1 upstream. - -So far when vlan id was added to team device befor port was added, this -vid was not added to port's vlan filter. Also after removal, vid stayed -in port device's vlan filter. Benefit of new vlan functions to handle -this work. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 79c2d1b..ed2a862 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -588,6 +588,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - goto err_dev_open; - } - -+ err = vlan_vids_add_by_dev(port_dev, dev); -+ if (err) { -+ netdev_err(dev, "Failed to add vlan ids to device %s\n", -+ portname); -+ goto err_vids_add; -+ } -+ - err = netdev_set_master(port_dev, dev); - if (err) { - netdev_err(dev, "Device %s failed to set master\n", portname); -@@ -615,6 +622,9 @@ err_handler_register: - netdev_set_master(port_dev, NULL); - - err_set_master: -+ vlan_vids_del_by_dev(port_dev, dev); -+ -+err_vids_add: - dev_close(port_dev); - - err_dev_open: -@@ -648,6 +658,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - team_adjust_ops(team); - netdev_rx_handler_unregister(port_dev); - netdev_set_master(port_dev, NULL); -+ vlan_vids_del_by_dev(port_dev, dev); - dev_close(port_dev); - team_port_leave(team, port); - team_port_set_orig_mac(port); diff --git a/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch b/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch deleted file mode 100644 index 1e8d7bb6b..000000000 --- a/debian/patches/features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch +++ /dev/null @@ -1,371 +0,0 @@ -From: Jiri Pirko -Date: Tue, 24 Jan 2012 05:16:00 +0000 -Subject: [12/23] team: send only changed options/ports via netlink - -commit b82b9183d4f18f9b8c4bb31f223eb6c79b734eb0 upstream. - -This patch changes event message behaviour to send only updated records -instead of whole list. This fixes bug on which userspace receives non-actual -data in case multiple events occur in row. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 136 +++++++++++++++++++++++++++++++---------------- - include/linux/if_team.h | 10 ++++ - 2 files changed, 100 insertions(+), 46 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index ed2a862..6b678f3 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -92,9 +92,9 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name) - return NULL; - } - --int team_options_register(struct team *team, -- const struct team_option *option, -- size_t option_count) -+int __team_options_register(struct team *team, -+ const struct team_option *option, -+ size_t option_count) - { - int i; - struct team_option **dst_opts; -@@ -116,8 +116,11 @@ int team_options_register(struct team *team, - } - } - -- for (i = 0; i < option_count; i++) -+ for (i = 0; i < option_count; i++) { -+ dst_opts[i]->changed = true; -+ dst_opts[i]->removed = false; - list_add_tail(&dst_opts[i]->list, &team->option_list); -+ } - - kfree(dst_opts); - return 0; -@@ -130,10 +133,22 @@ rollback: - return err; - } - --EXPORT_SYMBOL(team_options_register); -+static void __team_options_mark_removed(struct team *team, -+ const struct team_option *option, -+ size_t option_count) -+{ -+ int i; -+ -+ for (i = 0; i < option_count; i++, option++) { -+ struct team_option *del_opt; - --static void __team_options_change_check(struct team *team, -- struct team_option *changed_option); -+ del_opt = __team_find_option(team, option->name); -+ if (del_opt) { -+ del_opt->changed = true; -+ del_opt->removed = true; -+ } -+ } -+} - - static void __team_options_unregister(struct team *team, - const struct team_option *option, -@@ -152,12 +167,29 @@ static void __team_options_unregister(struct team *team, - } - } - -+static void __team_options_change_check(struct team *team); -+ -+int team_options_register(struct team *team, -+ const struct team_option *option, -+ size_t option_count) -+{ -+ int err; -+ -+ err = __team_options_register(team, option, option_count); -+ if (err) -+ return err; -+ __team_options_change_check(team); -+ return 0; -+} -+EXPORT_SYMBOL(team_options_register); -+ - void team_options_unregister(struct team *team, - const struct team_option *option, - size_t option_count) - { -+ __team_options_mark_removed(team, option, option_count); -+ __team_options_change_check(team); - __team_options_unregister(team, option, option_count); -- __team_options_change_check(team, NULL); - } - EXPORT_SYMBOL(team_options_unregister); - -@@ -176,7 +208,8 @@ static int team_option_set(struct team *team, struct team_option *option, - if (err) - return err; - -- __team_options_change_check(team, option); -+ option->changed = true; -+ __team_options_change_check(team); - return err; - } - -@@ -653,6 +686,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - return -ENOENT; - } - -+ port->removed = true; - __team_port_change_check(port, false); - team_port_list_del_port(team, port); - team_adjust_ops(team); -@@ -1200,10 +1234,9 @@ err_fill: - return err; - } - --static int team_nl_fill_options_get_changed(struct sk_buff *skb, -- u32 pid, u32 seq, int flags, -- struct team *team, -- struct team_option *changed_option) -+static int team_nl_fill_options_get(struct sk_buff *skb, -+ u32 pid, u32 seq, int flags, -+ struct team *team, bool fillall) - { - struct nlattr *option_list; - void *hdr; -@@ -1223,12 +1256,19 @@ static int team_nl_fill_options_get_changed(struct sk_buff *skb, - struct nlattr *option_item; - long arg; - -+ /* Include only changed options if fill all mode is not on */ -+ if (!fillall && !option->changed) -+ continue; - option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); - if (!option_item) - goto nla_put_failure; - NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); -- if (option == changed_option) -+ if (option->changed) { - NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); -+ option->changed = false; -+ } -+ if (option->removed) -+ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED); - switch (option->type) { - case TEAM_OPTION_TYPE_U32: - NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); -@@ -1255,13 +1295,13 @@ nla_put_failure: - return -EMSGSIZE; - } - --static int team_nl_fill_options_get(struct sk_buff *skb, -- struct genl_info *info, int flags, -- struct team *team) -+static int team_nl_fill_options_get_all(struct sk_buff *skb, -+ struct genl_info *info, int flags, -+ struct team *team) - { -- return team_nl_fill_options_get_changed(skb, info->snd_pid, -- info->snd_seq, NLM_F_ACK, -- team, NULL); -+ return team_nl_fill_options_get(skb, info->snd_pid, -+ info->snd_seq, NLM_F_ACK, -+ team, true); - } - - static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) -@@ -1273,7 +1313,7 @@ static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) - if (!team) - return -EINVAL; - -- err = team_nl_send_generic(info, team, team_nl_fill_options_get); -+ err = team_nl_send_generic(info, team, team_nl_fill_options_get_all); - - team_nl_team_put(team); - -@@ -1365,10 +1405,10 @@ team_put: - return err; - } - --static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, -- u32 pid, u32 seq, int flags, -- struct team *team, -- struct team_port *changed_port) -+static int team_nl_fill_port_list_get(struct sk_buff *skb, -+ u32 pid, u32 seq, int flags, -+ struct team *team, -+ bool fillall) - { - struct nlattr *port_list; - void *hdr; -@@ -1387,12 +1427,19 @@ static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, - list_for_each_entry(port, &team->port_list, list) { - struct nlattr *port_item; - -+ /* Include only changed ports if fill all mode is not on */ -+ if (!fillall && !port->changed) -+ continue; - port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); - if (!port_item) - goto nla_put_failure; - NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); -- if (port == changed_port) -+ if (port->changed) { - NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); -+ port->changed = false; -+ } -+ if (port->removed) -+ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED); - if (port->linkup) - NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); - NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); -@@ -1408,13 +1455,13 @@ nla_put_failure: - return -EMSGSIZE; - } - --static int team_nl_fill_port_list_get(struct sk_buff *skb, -- struct genl_info *info, int flags, -- struct team *team) -+static int team_nl_fill_port_list_get_all(struct sk_buff *skb, -+ struct genl_info *info, int flags, -+ struct team *team) - { -- return team_nl_fill_port_list_get_changed(skb, info->snd_pid, -- info->snd_seq, NLM_F_ACK, -- team, NULL); -+ return team_nl_fill_port_list_get(skb, info->snd_pid, -+ info->snd_seq, NLM_F_ACK, -+ team, true); - } - - static int team_nl_cmd_port_list_get(struct sk_buff *skb, -@@ -1427,7 +1474,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb, - if (!team) - return -EINVAL; - -- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get); -+ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all); - - team_nl_team_put(team); - -@@ -1464,8 +1511,7 @@ static struct genl_multicast_group team_change_event_mcgrp = { - .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, - }; - --static int team_nl_send_event_options_get(struct team *team, -- struct team_option *changed_option) -+static int team_nl_send_event_options_get(struct team *team) - { - struct sk_buff *skb; - int err; -@@ -1475,8 +1521,7 @@ static int team_nl_send_event_options_get(struct team *team, - if (!skb) - return -ENOMEM; - -- err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team, -- changed_option); -+ err = team_nl_fill_options_get(skb, 0, 0, 0, team, false); - if (err < 0) - goto err_fill; - -@@ -1489,18 +1534,17 @@ err_fill: - return err; - } - --static int team_nl_send_event_port_list_get(struct team_port *port) -+static int team_nl_send_event_port_list_get(struct team *team) - { - struct sk_buff *skb; - int err; -- struct net *net = dev_net(port->team->dev); -+ struct net *net = dev_net(team->dev); - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - -- err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0, -- port->team, port); -+ err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false); - if (err < 0) - goto err_fill; - -@@ -1544,12 +1588,11 @@ static void team_nl_fini(void) - * Change checkers - ******************/ - --static void __team_options_change_check(struct team *team, -- struct team_option *changed_option) -+static void __team_options_change_check(struct team *team) - { - int err; - -- err = team_nl_send_event_options_get(team, changed_option); -+ err = team_nl_send_event_options_get(team); - if (err) - netdev_warn(team->dev, "Failed to send options change via netlink\n"); - } -@@ -1559,9 +1602,10 @@ static void __team_port_change_check(struct team_port *port, bool linkup) - { - int err; - -- if (port->linkup == linkup) -+ if (!port->removed && port->linkup == linkup) - return; - -+ port->changed = true; - port->linkup = linkup; - if (linkup) { - struct ethtool_cmd ecmd; -@@ -1577,7 +1621,7 @@ static void __team_port_change_check(struct team_port *port, bool linkup) - port->duplex = 0; - - send_event: -- err = team_nl_send_event_port_list_get(port); -+ err = team_nl_send_event_port_list_get(port->team); - if (err) - netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", - port->dev->name); -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 828181f..58404b0 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -46,6 +46,10 @@ struct team_port { - u32 speed; - u8 duplex; - -+ /* Custom gennetlink interface related flags */ -+ bool changed; -+ bool removed; -+ - struct rcu_head rcu; - }; - -@@ -72,6 +76,10 @@ struct team_option { - enum team_option_type type; - int (*getter)(struct team *team, void *arg); - int (*setter)(struct team *team, void *arg); -+ -+ /* Custom gennetlink interface related flags */ -+ bool changed; -+ bool removed; - }; - - struct team_mode { -@@ -207,6 +215,7 @@ enum { - TEAM_ATTR_OPTION_CHANGED, /* flag */ - TEAM_ATTR_OPTION_TYPE, /* u8 */ - TEAM_ATTR_OPTION_DATA, /* dynamic */ -+ TEAM_ATTR_OPTION_REMOVED, /* flag */ - - __TEAM_ATTR_OPTION_MAX, - TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, -@@ -227,6 +236,7 @@ enum { - TEAM_ATTR_PORT_LINKUP, /* flag */ - TEAM_ATTR_PORT_SPEED, /* u32 */ - TEAM_ATTR_PORT_DUPLEX, /* u8 */ -+ TEAM_ATTR_PORT_REMOVED, /* flag */ - - __TEAM_ATTR_PORT_MAX, - TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, diff --git a/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch b/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch deleted file mode 100644 index 5f8f3a28c..000000000 --- a/debian/patches/features/all/team/0013-team-Stop-using-NLA_PUT.patch +++ /dev/null @@ -1,108 +0,0 @@ -From: "David S. Miller" -Date: Sun, 1 Apr 2012 20:25:18 -0400 -Subject: [13/23] team: Stop using NLA_PUT*(). - -commit 86ebb02dc793058ea17ad647c802b507dafff7cb upstream. - -These macros contain a hidden goto, and are thus extremely error -prone and make code hard to audit. - -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 50 +++++++++++++++++++++++++++++------------------ - 1 file changed, 31 insertions(+), 19 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 8f81805..0db6e66 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1248,7 +1248,8 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - if (IS_ERR(hdr)) - return PTR_ERR(hdr); - -- NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); -+ if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) -+ goto nla_put_failure; - option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION); - if (!option_list) - return -EMSGSIZE; -@@ -1263,24 +1264,31 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); - if (!option_item) - goto nla_put_failure; -- NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); -+ if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name)) -+ goto nla_put_failure; - if (option->changed) { -- NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); -+ if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED)) -+ goto nla_put_failure; - option->changed = false; - } -- if (option->removed) -- NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED); -+ if (option->removed && -+ nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED)) -+ goto nla_put_failure; - switch (option->type) { - case TEAM_OPTION_TYPE_U32: -- NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) -+ goto nla_put_failure; - team_option_get(team, option, &arg); -- NLA_PUT_U32(skb, TEAM_ATTR_OPTION_DATA, arg); -+ if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, arg)) -+ goto nla_put_failure; - break; - case TEAM_OPTION_TYPE_STRING: -- NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING); -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING)) -+ goto nla_put_failure; - team_option_get(team, option, &arg); -- NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_DATA, -- (char *) arg); -+ if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA, -+ (char *) arg)) -+ goto nla_put_failure; - break; - default: - BUG(); -@@ -1420,7 +1428,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, - if (IS_ERR(hdr)) - return PTR_ERR(hdr); - -- NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex); -+ if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) -+ goto nla_put_failure; - port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT); - if (!port_list) - return -EMSGSIZE; -@@ -1434,17 +1443,20 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, - port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); - if (!port_item) - goto nla_put_failure; -- NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); -+ if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) -+ goto nla_put_failure; - if (port->changed) { -- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); -+ if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) -+ goto nla_put_failure; - port->changed = false; - } -- if (port->removed) -- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED); -- if (port->linkup) -- NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); -- NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); -- NLA_PUT_U8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex); -+ if ((port->removed && -+ nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || -+ (port->linkup && -+ nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || -+ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->speed) || -+ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex)) -+ goto nla_put_failure; - nla_nest_end(skb, port_item); - } - diff --git a/debian/patches/features/all/team/0014-team-add-binary-option-type.patch b/debian/patches/features/all/team/0014-team-add-binary-option-type.patch deleted file mode 100644 index b1fadec16..000000000 --- a/debian/patches/features/all/team/0014-team-add-binary-option-type.patch +++ /dev/null @@ -1,124 +0,0 @@ -From: Jiri Pirko -Date: Wed, 4 Apr 2012 12:16:26 +0000 -Subject: [14/23] team: add binary option type - -commit 2615598fc100451c71b83d06bdf5faead619a40e upstream. - -For transfering generic binary data (e.g. BPF code), introduce new -binary option type. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 30 ++++++++++++++++++++++++++---- - include/linux/if_team.h | 8 ++++++++ - 2 files changed, 34 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 0db6e66..ea96f82 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1145,10 +1145,7 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { - }, - [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, - [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, -- [TEAM_ATTR_OPTION_DATA] = { -- .type = NLA_BINARY, -- .len = TEAM_STRING_MAX_LEN, -- }, -+ [TEAM_ATTR_OPTION_DATA] = { .type = NLA_BINARY }, - }; - - static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) -@@ -1257,6 +1254,7 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - list_for_each_entry(option, &team->option_list, list) { - struct nlattr *option_item; - long arg; -+ struct team_option_binary tbinary; - - /* Include only changed options if fill all mode is not on */ - if (!fillall && !option->changed) -@@ -1290,6 +1288,15 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - (char *) arg)) - goto nla_put_failure; - break; -+ case TEAM_OPTION_TYPE_BINARY: -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY)) -+ goto nla_put_failure; -+ arg = (long) &tbinary; -+ team_option_get(team, option, &arg); -+ if (nla_put(skb, TEAM_ATTR_OPTION_DATA, -+ tbinary.data_len, tbinary.data)) -+ goto nla_put_failure; -+ break; - default: - BUG(); - } -@@ -1374,6 +1381,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case NLA_STRING: - opt_type = TEAM_OPTION_TYPE_STRING; - break; -+ case NLA_BINARY: -+ opt_type = TEAM_OPTION_TYPE_BINARY; -+ break; - default: - goto team_put; - } -@@ -1382,19 +1392,31 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - list_for_each_entry(option, &team->option_list, list) { - long arg; - struct nlattr *opt_data_attr; -+ struct team_option_binary tbinary; -+ int data_len; - - if (option->type != opt_type || - strcmp(option->name, opt_name)) - continue; - opt_found = true; - opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; -+ data_len = nla_len(opt_data_attr); - switch (opt_type) { - case TEAM_OPTION_TYPE_U32: - arg = nla_get_u32(opt_data_attr); - break; - case TEAM_OPTION_TYPE_STRING: -+ if (data_len > TEAM_STRING_MAX_LEN) { -+ err = -EINVAL; -+ goto team_put; -+ } - arg = (long) nla_data(opt_data_attr); - break; -+ case TEAM_OPTION_TYPE_BINARY: -+ tbinary.data_len = data_len; -+ tbinary.data = nla_data(opt_data_attr); -+ arg = (long) &tbinary; -+ break; - default: - BUG(); - } -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 58404b0..41163ac 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -68,6 +68,7 @@ struct team_mode_ops { - enum team_option_type { - TEAM_OPTION_TYPE_U32, - TEAM_OPTION_TYPE_STRING, -+ TEAM_OPTION_TYPE_BINARY, - }; - - struct team_option { -@@ -82,6 +83,13 @@ struct team_option { - bool removed; - }; - -+struct team_option_binary { -+ u32 data_len; -+ void *data; -+}; -+ -+#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg)) -+ - struct team_mode { - struct list_head list; - const char *kind; diff --git a/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch b/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch deleted file mode 100644 index 3158c3010..000000000 --- a/debian/patches/features/all/team/0015-team-add-loadbalance-mode.patch +++ /dev/null @@ -1,241 +0,0 @@ -From: Jiri Pirko -Date: Wed, 4 Apr 2012 12:16:27 +0000 -Subject: [15/23] team: add loadbalance mode - -commit 01d7f30a9f962573b6c91ed520c73fb30658d826 upstream. - -This patch introduces new team mode. It's TX port is selected by -user-set BPF hash function. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/Kconfig | 11 ++ - drivers/net/team/Makefile | 1 + - drivers/net/team/team_mode_loadbalance.c | 188 ++++++++++++++++++++++++++++++ - 3 files changed, 200 insertions(+) - create mode 100644 drivers/net/team/team_mode_loadbalance.c - -diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig -index 248a144..89024d5 100644 ---- a/drivers/net/team/Kconfig -+++ b/drivers/net/team/Kconfig -@@ -40,4 +40,15 @@ config NET_TEAM_MODE_ACTIVEBACKUP - To compile this team mode as a module, choose M here: the module - will be called team_mode_activebackup. - -+config NET_TEAM_MODE_LOADBALANCE -+ tristate "Load-balance mode support" -+ depends on NET_TEAM -+ ---help--- -+ This mode provides load balancing functionality. Tx port selection -+ is done using BPF function set up from userspace (bpf_hash_func -+ option) -+ -+ To compile this team mode as a module, choose M here: the module -+ will be called team_mode_loadbalance. -+ - endif # NET_TEAM -diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile -index 85f2028..fb9f4c1 100644 ---- a/drivers/net/team/Makefile -+++ b/drivers/net/team/Makefile -@@ -5,3 +5,4 @@ - obj-$(CONFIG_NET_TEAM) += team.o - obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o - obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o -+obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -new file mode 100644 -index 0000000..ed20f39 ---- /dev/null -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -0,0 +1,188 @@ -+/* -+ * drivers/net/team/team_mode_loadbalance.c - Load-balancing mode for team -+ * Copyright (c) 2012 Jiri Pirko -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct lb_priv { -+ struct sk_filter __rcu *fp; -+ struct sock_fprog *orig_fprog; -+}; -+ -+static struct lb_priv *lb_priv(struct team *team) -+{ -+ return (struct lb_priv *) &team->mode_priv; -+} -+ -+static bool lb_transmit(struct team *team, struct sk_buff *skb) -+{ -+ struct sk_filter *fp; -+ struct team_port *port; -+ unsigned int hash; -+ int port_index; -+ -+ fp = rcu_dereference(lb_priv(team)->fp); -+ if (unlikely(!fp)) -+ goto drop; -+ hash = SK_RUN_FILTER(fp, skb); -+ port_index = hash % team->port_count; -+ port = team_get_port_by_index_rcu(team, port_index); -+ if (unlikely(!port)) -+ goto drop; -+ skb->dev = port->dev; -+ if (dev_queue_xmit(skb)) -+ return false; -+ return true; -+ -+drop: -+ dev_kfree_skb_any(skb); -+ return false; -+} -+ -+static int lb_bpf_func_get(struct team *team, void *arg) -+{ -+ struct team_option_binary *tbinary = team_optarg_tbinary(arg); -+ -+ memset(tbinary, 0, sizeof(*tbinary)); -+ if (!lb_priv(team)->orig_fprog) -+ return 0; -+ -+ tbinary->data_len = lb_priv(team)->orig_fprog->len * -+ sizeof(struct sock_filter); -+ tbinary->data = lb_priv(team)->orig_fprog->filter; -+ return 0; -+} -+ -+static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, -+ void *data) -+{ -+ struct sock_fprog *fprog; -+ struct sock_filter *filter = (struct sock_filter *) data; -+ -+ if (data_len % sizeof(struct sock_filter)) -+ return -EINVAL; -+ fprog = kmalloc(sizeof(struct sock_fprog), GFP_KERNEL); -+ if (!fprog) -+ return -ENOMEM; -+ fprog->filter = kmemdup(filter, data_len, GFP_KERNEL); -+ if (!fprog->filter) { -+ kfree(fprog); -+ return -ENOMEM; -+ } -+ fprog->len = data_len / sizeof(struct sock_filter); -+ *pfprog = fprog; -+ return 0; -+} -+ -+static void __fprog_destroy(struct sock_fprog *fprog) -+{ -+ kfree(fprog->filter); -+ kfree(fprog); -+} -+ -+static int lb_bpf_func_set(struct team *team, void *arg) -+{ -+ struct team_option_binary *tbinary = team_optarg_tbinary(arg); -+ struct sk_filter *fp = NULL; -+ struct sock_fprog *fprog = NULL; -+ int err; -+ -+ if (tbinary->data_len) { -+ err = __fprog_create(&fprog, tbinary->data_len, -+ tbinary->data); -+ if (err) -+ return err; -+ err = sk_unattached_filter_create(&fp, fprog); -+ if (err) { -+ __fprog_destroy(fprog); -+ return err; -+ } -+ } -+ -+ if (lb_priv(team)->orig_fprog) { -+ /* Clear old filter data */ -+ __fprog_destroy(lb_priv(team)->orig_fprog); -+ sk_unattached_filter_destroy(lb_priv(team)->fp); -+ } -+ -+ rcu_assign_pointer(lb_priv(team)->fp, fp); -+ lb_priv(team)->orig_fprog = fprog; -+ return 0; -+} -+ -+static const struct team_option lb_options[] = { -+ { -+ .name = "bpf_hash_func", -+ .type = TEAM_OPTION_TYPE_BINARY, -+ .getter = lb_bpf_func_get, -+ .setter = lb_bpf_func_set, -+ }, -+}; -+ -+int lb_init(struct team *team) -+{ -+ return team_options_register(team, lb_options, -+ ARRAY_SIZE(lb_options)); -+} -+ -+void lb_exit(struct team *team) -+{ -+ team_options_unregister(team, lb_options, -+ ARRAY_SIZE(lb_options)); -+} -+ -+static int lb_port_enter(struct team *team, struct team_port *port) -+{ -+ return team_port_set_team_mac(port); -+} -+ -+static void lb_port_change_mac(struct team *team, struct team_port *port) -+{ -+ team_port_set_team_mac(port); -+} -+ -+static const struct team_mode_ops lb_mode_ops = { -+ .init = lb_init, -+ .exit = lb_exit, -+ .transmit = lb_transmit, -+ .port_enter = lb_port_enter, -+ .port_change_mac = lb_port_change_mac, -+}; -+ -+static struct team_mode lb_mode = { -+ .kind = "loadbalance", -+ .owner = THIS_MODULE, -+ .priv_size = sizeof(struct lb_priv), -+ .ops = &lb_mode_ops, -+}; -+ -+static int __init lb_init_module(void) -+{ -+ return team_mode_register(&lb_mode); -+} -+ -+static void __exit lb_cleanup_module(void) -+{ -+ team_mode_unregister(&lb_mode); -+} -+ -+module_init(lb_init_module); -+module_exit(lb_cleanup_module); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Jiri Pirko "); -+MODULE_DESCRIPTION("Load-balancing mode for team"); -+MODULE_ALIAS("team-mode-loadbalance"); diff --git a/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch b/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch deleted file mode 100644 index 204877e6a..000000000 --- a/debian/patches/features/all/team/0016-team-add-support-for-per-port-options.patch +++ /dev/null @@ -1,687 +0,0 @@ -From: Jiri Pirko -Date: Tue, 10 Apr 2012 05:15:42 +0000 -Subject: [16/23] team: add support for per-port options - -commit 80f7c6683fe0e891ef1db7c967d538b5fdddd22c upstream. - -This patch allows to create per-port options. That becomes handy for all -sorts of stuff, for example for userspace driven link-state, 802.3ad -implementation and so on. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 306 +++++++++++++++++++++++------ - drivers/net/team/team_mode_activebackup.c | 14 +- - drivers/net/team/team_mode_loadbalance.c | 28 ++- - include/linux/if_team.h | 30 +-- - 4 files changed, 278 insertions(+), 100 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index ea96f82..eaf8441 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -81,7 +81,16 @@ EXPORT_SYMBOL(team_port_set_team_mac); - * Options handling - *******************/ - --struct team_option *__team_find_option(struct team *team, const char *opt_name) -+struct team_option_inst { /* One for each option instance */ -+ struct list_head list; -+ struct team_option *option; -+ struct team_port *port; /* != NULL if per-port */ -+ bool changed; -+ bool removed; -+}; -+ -+static struct team_option *__team_find_option(struct team *team, -+ const char *opt_name) - { - struct team_option *option; - -@@ -92,9 +101,121 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name) - return NULL; - } - --int __team_options_register(struct team *team, -- const struct team_option *option, -- size_t option_count) -+static int __team_option_inst_add(struct team *team, struct team_option *option, -+ struct team_port *port) -+{ -+ struct team_option_inst *opt_inst; -+ -+ opt_inst = kmalloc(sizeof(*opt_inst), GFP_KERNEL); -+ if (!opt_inst) -+ return -ENOMEM; -+ opt_inst->option = option; -+ opt_inst->port = port; -+ opt_inst->changed = true; -+ opt_inst->removed = false; -+ list_add_tail(&opt_inst->list, &team->option_inst_list); -+ return 0; -+} -+ -+static void __team_option_inst_del(struct team_option_inst *opt_inst) -+{ -+ list_del(&opt_inst->list); -+ kfree(opt_inst); -+} -+ -+static void __team_option_inst_del_option(struct team *team, -+ struct team_option *option) -+{ -+ struct team_option_inst *opt_inst, *tmp; -+ -+ list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) { -+ if (opt_inst->option == option) -+ __team_option_inst_del(opt_inst); -+ } -+} -+ -+static int __team_option_inst_add_option(struct team *team, -+ struct team_option *option) -+{ -+ struct team_port *port; -+ int err; -+ -+ if (!option->per_port) -+ return __team_option_inst_add(team, option, 0); -+ -+ list_for_each_entry(port, &team->port_list, list) { -+ err = __team_option_inst_add(team, option, port); -+ if (err) -+ goto inst_del_option; -+ } -+ return 0; -+ -+inst_del_option: -+ __team_option_inst_del_option(team, option); -+ return err; -+} -+ -+static void __team_option_inst_mark_removed_option(struct team *team, -+ struct team_option *option) -+{ -+ struct team_option_inst *opt_inst; -+ -+ list_for_each_entry(opt_inst, &team->option_inst_list, list) { -+ if (opt_inst->option == option) { -+ opt_inst->changed = true; -+ opt_inst->removed = true; -+ } -+ } -+} -+ -+static void __team_option_inst_del_port(struct team *team, -+ struct team_port *port) -+{ -+ struct team_option_inst *opt_inst, *tmp; -+ -+ list_for_each_entry_safe(opt_inst, tmp, &team->option_inst_list, list) { -+ if (opt_inst->option->per_port && -+ opt_inst->port == port) -+ __team_option_inst_del(opt_inst); -+ } -+} -+ -+static int __team_option_inst_add_port(struct team *team, -+ struct team_port *port) -+{ -+ struct team_option *option; -+ int err; -+ -+ list_for_each_entry(option, &team->option_list, list) { -+ if (!option->per_port) -+ continue; -+ err = __team_option_inst_add(team, option, port); -+ if (err) -+ goto inst_del_port; -+ } -+ return 0; -+ -+inst_del_port: -+ __team_option_inst_del_port(team, port); -+ return err; -+} -+ -+static void __team_option_inst_mark_removed_port(struct team *team, -+ struct team_port *port) -+{ -+ struct team_option_inst *opt_inst; -+ -+ list_for_each_entry(opt_inst, &team->option_inst_list, list) { -+ if (opt_inst->port == port) { -+ opt_inst->changed = true; -+ opt_inst->removed = true; -+ } -+ } -+} -+ -+static int __team_options_register(struct team *team, -+ const struct team_option *option, -+ size_t option_count) - { - int i; - struct team_option **dst_opts; -@@ -107,26 +228,32 @@ int __team_options_register(struct team *team, - for (i = 0; i < option_count; i++, option++) { - if (__team_find_option(team, option->name)) { - err = -EEXIST; -- goto rollback; -+ goto alloc_rollback; - } - dst_opts[i] = kmemdup(option, sizeof(*option), GFP_KERNEL); - if (!dst_opts[i]) { - err = -ENOMEM; -- goto rollback; -+ goto alloc_rollback; - } - } - - for (i = 0; i < option_count; i++) { -- dst_opts[i]->changed = true; -- dst_opts[i]->removed = false; -+ err = __team_option_inst_add_option(team, dst_opts[i]); -+ if (err) -+ goto inst_rollback; - list_add_tail(&dst_opts[i]->list, &team->option_list); - } - - kfree(dst_opts); - return 0; - --rollback: -- for (i = 0; i < option_count; i++) -+inst_rollback: -+ for (i--; i >= 0; i--) -+ __team_option_inst_del_option(team, dst_opts[i]); -+ -+ i = option_count - 1; -+alloc_rollback: -+ for (i--; i >= 0; i--) - kfree(dst_opts[i]); - - kfree(dst_opts); -@@ -143,10 +270,8 @@ static void __team_options_mark_removed(struct team *team, - struct team_option *del_opt; - - del_opt = __team_find_option(team, option->name); -- if (del_opt) { -- del_opt->changed = true; -- del_opt->removed = true; -- } -+ if (del_opt) -+ __team_option_inst_mark_removed_option(team, del_opt); - } - } - -@@ -161,6 +286,7 @@ static void __team_options_unregister(struct team *team, - - del_opt = __team_find_option(team, option->name); - if (del_opt) { -+ __team_option_inst_del_option(team, del_opt); - list_del(&del_opt->list); - kfree(del_opt); - } -@@ -193,22 +319,42 @@ void team_options_unregister(struct team *team, - } - EXPORT_SYMBOL(team_options_unregister); - --static int team_option_get(struct team *team, struct team_option *option, -- void *arg) -+static int team_option_port_add(struct team *team, struct team_port *port) - { -- return option->getter(team, arg); -+ int err; -+ -+ err = __team_option_inst_add_port(team, port); -+ if (err) -+ return err; -+ __team_options_change_check(team); -+ return 0; - } - --static int team_option_set(struct team *team, struct team_option *option, -- void *arg) -+static void team_option_port_del(struct team *team, struct team_port *port) -+{ -+ __team_option_inst_mark_removed_port(team, port); -+ __team_options_change_check(team); -+ __team_option_inst_del_port(team, port); -+} -+ -+static int team_option_get(struct team *team, -+ struct team_option_inst *opt_inst, -+ struct team_gsetter_ctx *ctx) -+{ -+ return opt_inst->option->getter(team, ctx); -+} -+ -+static int team_option_set(struct team *team, -+ struct team_option_inst *opt_inst, -+ struct team_gsetter_ctx *ctx) - { - int err; - -- err = option->setter(team, arg); -+ err = opt_inst->option->setter(team, ctx); - if (err) - return err; - -- option->changed = true; -+ opt_inst->changed = true; - __team_options_change_check(team); - return err; - } -@@ -642,6 +788,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - goto err_handler_register; - } - -+ err = team_option_port_add(team, port); -+ if (err) { -+ netdev_err(dev, "Device %s failed to add per-port options\n", -+ portname); -+ goto err_option_port_add; -+ } -+ - team_port_list_add_port(team, port); - team_adjust_ops(team); - __team_compute_features(team); -@@ -651,6 +804,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - - return 0; - -+err_option_port_add: -+ netdev_rx_handler_unregister(port_dev); -+ - err_handler_register: - netdev_set_master(port_dev, NULL); - -@@ -690,6 +846,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - __team_port_change_check(port, false); - team_port_list_del_port(team, port); - team_adjust_ops(team); -+ team_option_port_del(team, port); - netdev_rx_handler_unregister(port_dev); - netdev_set_master(port_dev, NULL); - vlan_vids_del_by_dev(port_dev, dev); -@@ -712,19 +869,15 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - - static const char team_no_mode_kind[] = "*NOMODE*"; - --static int team_mode_option_get(struct team *team, void *arg) -+static int team_mode_option_get(struct team *team, struct team_gsetter_ctx *ctx) - { -- const char **str = arg; -- -- *str = team->mode ? team->mode->kind : team_no_mode_kind; -+ ctx->data.str_val = team->mode ? team->mode->kind : team_no_mode_kind; - return 0; - } - --static int team_mode_option_set(struct team *team, void *arg) -+static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) - { -- const char **str = arg; -- -- return team_change_mode(team, *str); -+ return team_change_mode(team, ctx->data.str_val); - } - - static const struct team_option team_options[] = { -@@ -756,6 +909,7 @@ static int team_init(struct net_device *dev) - team_adjust_ops(team); - - INIT_LIST_HEAD(&team->option_list); -+ INIT_LIST_HEAD(&team->option_inst_list); - err = team_options_register(team, team_options, ARRAY_SIZE(team_options)); - if (err) - goto err_options_register; -@@ -1238,7 +1392,8 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - { - struct nlattr *option_list; - void *hdr; -- struct team_option *option; -+ struct team_option_inst *opt_inst; -+ int err; - - hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags, - TEAM_CMD_OPTIONS_GET); -@@ -1251,50 +1406,61 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - if (!option_list) - return -EMSGSIZE; - -- list_for_each_entry(option, &team->option_list, list) { -+ list_for_each_entry(opt_inst, &team->option_inst_list, list) { - struct nlattr *option_item; -- long arg; -- struct team_option_binary tbinary; -+ struct team_option *option = opt_inst->option; -+ struct team_gsetter_ctx ctx; - - /* Include only changed options if fill all mode is not on */ -- if (!fillall && !option->changed) -+ if (!fillall && !opt_inst->changed) - continue; - option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); - if (!option_item) - goto nla_put_failure; - if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name)) - goto nla_put_failure; -- if (option->changed) { -+ if (opt_inst->changed) { - if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED)) - goto nla_put_failure; -- option->changed = false; -+ opt_inst->changed = false; - } -- if (option->removed && -+ if (opt_inst->removed && - nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED)) - goto nla_put_failure; -+ if (opt_inst->port && -+ nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX, -+ opt_inst->port->dev->ifindex)) -+ goto nla_put_failure; -+ ctx.port = opt_inst->port; - switch (option->type) { - case TEAM_OPTION_TYPE_U32: - if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) - goto nla_put_failure; -- team_option_get(team, option, &arg); -- if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, arg)) -+ err = team_option_get(team, opt_inst, &ctx); -+ if (err) -+ goto errout; -+ if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, -+ ctx.data.u32_val)) - goto nla_put_failure; - break; - case TEAM_OPTION_TYPE_STRING: - if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING)) - goto nla_put_failure; -- team_option_get(team, option, &arg); -+ err = team_option_get(team, opt_inst, &ctx); -+ if (err) -+ goto errout; - if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA, -- (char *) arg)) -+ ctx.data.str_val)) - goto nla_put_failure; - break; - case TEAM_OPTION_TYPE_BINARY: - if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY)) - goto nla_put_failure; -- arg = (long) &tbinary; -- team_option_get(team, option, &arg); -+ err = team_option_get(team, opt_inst, &ctx); -+ if (err) -+ goto errout; - if (nla_put(skb, TEAM_ATTR_OPTION_DATA, -- tbinary.data_len, tbinary.data)) -+ ctx.data.bin_val.len, ctx.data.bin_val.ptr)) - goto nla_put_failure; - break; - default: -@@ -1307,8 +1473,10 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - return genlmsg_end(skb, hdr); - - nla_put_failure: -+ err = -EMSGSIZE; -+errout: - genlmsg_cancel(skb, hdr); -- return -EMSGSIZE; -+ return err; - } - - static int team_nl_fill_options_get_all(struct sk_buff *skb, -@@ -1354,9 +1522,11 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - } - - nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { -- struct nlattr *mode_attrs[TEAM_ATTR_OPTION_MAX + 1]; -+ struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; -+ struct nlattr *attr_port_ifindex; - enum team_option_type opt_type; -- struct team_option *option; -+ int opt_port_ifindex = 0; /* != 0 for per-port options */ -+ struct team_option_inst *opt_inst; - char *opt_name; - bool opt_found = false; - -@@ -1364,17 +1534,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - err = -EINVAL; - goto team_put; - } -- err = nla_parse_nested(mode_attrs, TEAM_ATTR_OPTION_MAX, -+ err = nla_parse_nested(opt_attrs, TEAM_ATTR_OPTION_MAX, - nl_option, team_nl_option_policy); - if (err) - goto team_put; -- if (!mode_attrs[TEAM_ATTR_OPTION_NAME] || -- !mode_attrs[TEAM_ATTR_OPTION_TYPE] || -- !mode_attrs[TEAM_ATTR_OPTION_DATA]) { -+ if (!opt_attrs[TEAM_ATTR_OPTION_NAME] || -+ !opt_attrs[TEAM_ATTR_OPTION_TYPE] || -+ !opt_attrs[TEAM_ATTR_OPTION_DATA]) { - err = -EINVAL; - goto team_put; - } -- switch (nla_get_u8(mode_attrs[TEAM_ATTR_OPTION_TYPE])) { -+ switch (nla_get_u8(opt_attrs[TEAM_ATTR_OPTION_TYPE])) { - case NLA_U32: - opt_type = TEAM_OPTION_TYPE_U32; - break; -@@ -1388,39 +1558,47 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - goto team_put; - } - -- opt_name = nla_data(mode_attrs[TEAM_ATTR_OPTION_NAME]); -- list_for_each_entry(option, &team->option_list, list) { -- long arg; -+ opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]); -+ attr_port_ifindex = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX]; -+ if (attr_port_ifindex) -+ opt_port_ifindex = nla_get_u32(attr_port_ifindex); -+ -+ list_for_each_entry(opt_inst, &team->option_inst_list, list) { -+ struct team_option *option = opt_inst->option; - struct nlattr *opt_data_attr; -- struct team_option_binary tbinary; -+ struct team_gsetter_ctx ctx; - int data_len; -+ int tmp_ifindex; - -+ tmp_ifindex = opt_inst->port ? -+ opt_inst->port->dev->ifindex : 0; - if (option->type != opt_type || -- strcmp(option->name, opt_name)) -+ strcmp(option->name, opt_name) || -+ tmp_ifindex != opt_port_ifindex) - continue; - opt_found = true; -- opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA]; -+ opt_data_attr = opt_attrs[TEAM_ATTR_OPTION_DATA]; - data_len = nla_len(opt_data_attr); -+ ctx.port = opt_inst->port; - switch (opt_type) { - case TEAM_OPTION_TYPE_U32: -- arg = nla_get_u32(opt_data_attr); -+ ctx.data.u32_val = nla_get_u32(opt_data_attr); - break; - case TEAM_OPTION_TYPE_STRING: - if (data_len > TEAM_STRING_MAX_LEN) { - err = -EINVAL; - goto team_put; - } -- arg = (long) nla_data(opt_data_attr); -+ ctx.data.str_val = nla_data(opt_data_attr); - break; - case TEAM_OPTION_TYPE_BINARY: -- tbinary.data_len = data_len; -- tbinary.data = nla_data(opt_data_attr); -- arg = (long) &tbinary; -+ ctx.data.bin_val.len = data_len; -+ ctx.data.bin_val.ptr = nla_data(opt_data_attr); - break; - default: - BUG(); - } -- err = team_option_set(team, option, &arg); -+ err = team_option_set(team, opt_inst, &ctx); - if (err) - goto team_put; - } -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -index f4d960e..6cde1ab 100644 ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -59,23 +59,21 @@ static void ab_port_leave(struct team *team, struct team_port *port) - RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); - } - --static int ab_active_port_get(struct team *team, void *arg) -+static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) - { -- u32 *ifindex = arg; -- -- *ifindex = 0; - if (ab_priv(team)->active_port) -- *ifindex = ab_priv(team)->active_port->dev->ifindex; -+ ctx->data.u32_val = ab_priv(team)->active_port->dev->ifindex; -+ else -+ ctx->data.u32_val = 0; - return 0; - } - --static int ab_active_port_set(struct team *team, void *arg) -+static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx) - { -- u32 *ifindex = arg; - struct team_port *port; - - list_for_each_entry_rcu(port, &team->port_list, list) { -- if (port->dev->ifindex == *ifindex) { -+ if (port->dev->ifindex == ctx->data.u32_val) { - rcu_assign_pointer(ab_priv(team)->active_port, port); - return 0; - } -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -index ed20f39..167cdb4 100644 ---- a/drivers/net/team/team_mode_loadbalance.c -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -52,22 +52,21 @@ drop: - return false; - } - --static int lb_bpf_func_get(struct team *team, void *arg) -+static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) - { -- struct team_option_binary *tbinary = team_optarg_tbinary(arg); -- -- memset(tbinary, 0, sizeof(*tbinary)); -- if (!lb_priv(team)->orig_fprog) -+ if (!lb_priv(team)->orig_fprog) { -+ ctx->data.bin_val.len = 0; -+ ctx->data.bin_val.ptr = NULL; - return 0; -- -- tbinary->data_len = lb_priv(team)->orig_fprog->len * -- sizeof(struct sock_filter); -- tbinary->data = lb_priv(team)->orig_fprog->filter; -+ } -+ ctx->data.bin_val.len = lb_priv(team)->orig_fprog->len * -+ sizeof(struct sock_filter); -+ ctx->data.bin_val.ptr = lb_priv(team)->orig_fprog->filter; - return 0; - } - - static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, -- void *data) -+ const void *data) - { - struct sock_fprog *fprog; - struct sock_filter *filter = (struct sock_filter *) data; -@@ -93,16 +92,15 @@ static void __fprog_destroy(struct sock_fprog *fprog) - kfree(fprog); - } - --static int lb_bpf_func_set(struct team *team, void *arg) -+static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) - { -- struct team_option_binary *tbinary = team_optarg_tbinary(arg); - struct sk_filter *fp = NULL; - struct sock_fprog *fprog = NULL; - int err; - -- if (tbinary->data_len) { -- err = __fprog_create(&fprog, tbinary->data_len, -- tbinary->data); -+ if (ctx->data.bin_val.len) { -+ err = __fprog_create(&fprog, ctx->data.bin_val.len, -+ ctx->data.bin_val.ptr); - if (err) - return err; - err = sk_unattached_filter_create(&fp, fprog); -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 41163ac..6f27c84 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -71,25 +71,27 @@ enum team_option_type { - TEAM_OPTION_TYPE_BINARY, - }; - -+struct team_gsetter_ctx { -+ union { -+ u32 u32_val; -+ const char *str_val; -+ struct { -+ const void *ptr; -+ u32 len; -+ } bin_val; -+ } data; -+ struct team_port *port; -+}; -+ - struct team_option { - struct list_head list; - const char *name; -+ bool per_port; - enum team_option_type type; -- int (*getter)(struct team *team, void *arg); -- int (*setter)(struct team *team, void *arg); -- -- /* Custom gennetlink interface related flags */ -- bool changed; -- bool removed; -+ int (*getter)(struct team *team, struct team_gsetter_ctx *ctx); -+ int (*setter)(struct team *team, struct team_gsetter_ctx *ctx); - }; - --struct team_option_binary { -- u32 data_len; -- void *data; --}; -- --#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg)) -- - struct team_mode { - struct list_head list; - const char *kind; -@@ -118,6 +120,7 @@ struct team { - struct list_head port_list; - - struct list_head option_list; -+ struct list_head option_inst_list; /* list of option instances */ - - const struct team_mode *mode; - struct team_mode_ops ops; -@@ -224,6 +227,7 @@ enum { - TEAM_ATTR_OPTION_TYPE, /* u8 */ - TEAM_ATTR_OPTION_DATA, /* dynamic */ - TEAM_ATTR_OPTION_REMOVED, /* flag */ -+ TEAM_ATTR_OPTION_PORT_IFINDEX, /* u32 */ /* for per-port options */ - - __TEAM_ATTR_OPTION_MAX, - TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, diff --git a/debian/patches/features/all/team/0017-team-add-bool-option-type.patch b/debian/patches/features/all/team/0017-team-add-bool-option-type.patch deleted file mode 100644 index 077e46621..000000000 --- a/debian/patches/features/all/team/0017-team-add-bool-option-type.patch +++ /dev/null @@ -1,137 +0,0 @@ -From: Jiri Pirko -Date: Tue, 10 Apr 2012 05:15:43 +0000 -Subject: [17/23] team: add bool option type - -commit 14f066bab19946545130a7379f420af860a02ae8 upstream. - -Add another (hopefully last) option type. Use NLA_FLAG to implement -that. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 40 +++++++++++++++++++++++++++++----------- - include/linux/if_team.h | 2 ++ - 2 files changed, 31 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index eaf8441..2645fae 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1463,6 +1463,16 @@ static int team_nl_fill_options_get(struct sk_buff *skb, - ctx.data.bin_val.len, ctx.data.bin_val.ptr)) - goto nla_put_failure; - break; -+ case TEAM_OPTION_TYPE_BOOL: -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_FLAG)) -+ goto nla_put_failure; -+ err = team_option_get(team, opt_inst, &ctx); -+ if (err) -+ goto errout; -+ if (ctx.data.bool_val && -+ nla_put_flag(skb, TEAM_ATTR_OPTION_DATA)) -+ goto nla_put_failure; -+ break; - default: - BUG(); - } -@@ -1524,6 +1534,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { - struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; - struct nlattr *attr_port_ifindex; -+ struct nlattr *attr_data; - enum team_option_type opt_type; - int opt_port_ifindex = 0; /* != 0 for per-port options */ - struct team_option_inst *opt_inst; -@@ -1539,8 +1550,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - if (err) - goto team_put; - if (!opt_attrs[TEAM_ATTR_OPTION_NAME] || -- !opt_attrs[TEAM_ATTR_OPTION_TYPE] || -- !opt_attrs[TEAM_ATTR_OPTION_DATA]) { -+ !opt_attrs[TEAM_ATTR_OPTION_TYPE]) { - err = -EINVAL; - goto team_put; - } -@@ -1554,10 +1564,19 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case NLA_BINARY: - opt_type = TEAM_OPTION_TYPE_BINARY; - break; -+ case NLA_FLAG: -+ opt_type = TEAM_OPTION_TYPE_BOOL; -+ break; - default: - goto team_put; - } - -+ attr_data = opt_attrs[TEAM_ATTR_OPTION_DATA]; -+ if (opt_type != TEAM_OPTION_TYPE_BOOL && !attr_data) { -+ err = -EINVAL; -+ goto team_put; -+ } -+ - opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]); - attr_port_ifindex = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX]; - if (attr_port_ifindex) -@@ -1565,9 +1584,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - - list_for_each_entry(opt_inst, &team->option_inst_list, list) { - struct team_option *option = opt_inst->option; -- struct nlattr *opt_data_attr; - struct team_gsetter_ctx ctx; -- int data_len; - int tmp_ifindex; - - tmp_ifindex = opt_inst->port ? -@@ -1577,23 +1594,24 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - tmp_ifindex != opt_port_ifindex) - continue; - opt_found = true; -- opt_data_attr = opt_attrs[TEAM_ATTR_OPTION_DATA]; -- data_len = nla_len(opt_data_attr); - ctx.port = opt_inst->port; - switch (opt_type) { - case TEAM_OPTION_TYPE_U32: -- ctx.data.u32_val = nla_get_u32(opt_data_attr); -+ ctx.data.u32_val = nla_get_u32(attr_data); - break; - case TEAM_OPTION_TYPE_STRING: -- if (data_len > TEAM_STRING_MAX_LEN) { -+ if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) { - err = -EINVAL; - goto team_put; - } -- ctx.data.str_val = nla_data(opt_data_attr); -+ ctx.data.str_val = nla_data(attr_data); - break; - case TEAM_OPTION_TYPE_BINARY: -- ctx.data.bin_val.len = data_len; -- ctx.data.bin_val.ptr = nla_data(opt_data_attr); -+ ctx.data.bin_val.len = nla_len(attr_data); -+ ctx.data.bin_val.ptr = nla_data(attr_data); -+ break; -+ case TEAM_OPTION_TYPE_BOOL: -+ ctx.data.bool_val = attr_data ? true : false; - break; - default: - BUG(); -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 6f27c84..78c84fd 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -69,6 +69,7 @@ enum team_option_type { - TEAM_OPTION_TYPE_U32, - TEAM_OPTION_TYPE_STRING, - TEAM_OPTION_TYPE_BINARY, -+ TEAM_OPTION_TYPE_BOOL, - }; - - struct team_gsetter_ctx { -@@ -79,6 +80,7 @@ struct team_gsetter_ctx { - const void *ptr; - u32 len; - } bin_val; -+ bool bool_val; - } data; - struct team_port *port; - }; diff --git a/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch b/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch deleted file mode 100644 index 1dadd07c6..000000000 --- a/debian/patches/features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch +++ /dev/null @@ -1,184 +0,0 @@ -From: Jiri Pirko -Date: Tue, 10 Apr 2012 05:15:44 +0000 -Subject: [18/23] team: add user_linkup and user_linkup_enabled per-port - option - -commit 71472ec12c61dd305ab4d11822af7ecc4f9717f9 upstream. - -Allows userspace to setup linkup for ports. Default is to take linkup -directly from ethtool state. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 72 +++++++++++++++++++++++++++++++++++++++++------ - include/linux/if_team.h | 26 +++++++++++------ - 2 files changed, 81 insertions(+), 17 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 2645fae..e639abe 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -76,6 +76,11 @@ int team_port_set_team_mac(struct team_port *port) - } - EXPORT_SYMBOL(team_port_set_team_mac); - -+static void team_refresh_port_linkup(struct team_port *port) -+{ -+ port->linkup = port->user.linkup_enabled ? port->user.linkup : -+ port->state.linkup; -+} - - /******************* - * Options handling -@@ -880,6 +885,40 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) - return team_change_mode(team, ctx->data.str_val); - } - -+static int team_user_linkup_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ ctx->data.bool_val = ctx->port->user.linkup; -+ return 0; -+} -+ -+static int team_user_linkup_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ ctx->port->user.linkup = ctx->data.bool_val; -+ team_refresh_port_linkup(ctx->port); -+ return 0; -+} -+ -+static int team_user_linkup_en_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->port; -+ -+ ctx->data.bool_val = port->user.linkup_enabled; -+ return 0; -+} -+ -+static int team_user_linkup_en_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->port; -+ -+ port->user.linkup_enabled = ctx->data.bool_val; -+ team_refresh_port_linkup(ctx->port); -+ return 0; -+} -+ - static const struct team_option team_options[] = { - { - .name = "mode", -@@ -887,6 +926,20 @@ static const struct team_option team_options[] = { - .getter = team_mode_option_get, - .setter = team_mode_option_set, - }, -+ { -+ .name = "user_linkup", -+ .type = TEAM_OPTION_TYPE_BOOL, -+ .per_port = true, -+ .getter = team_user_linkup_option_get, -+ .setter = team_user_linkup_option_set, -+ }, -+ { -+ .name = "user_linkup_enabled", -+ .type = TEAM_OPTION_TYPE_BOOL, -+ .per_port = true, -+ .getter = team_user_linkup_en_option_get, -+ .setter = team_user_linkup_en_option_set, -+ }, - }; - - static int team_init(struct net_device *dev) -@@ -1670,10 +1723,10 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, - } - if ((port->removed && - nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || -- (port->linkup && -+ (port->state.linkup && - nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || -- nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->speed) || -- nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex)) -+ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || -+ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) - goto nla_put_failure; - nla_nest_end(skb, port_item); - } -@@ -1833,23 +1886,24 @@ static void __team_port_change_check(struct team_port *port, bool linkup) - { - int err; - -- if (!port->removed && port->linkup == linkup) -+ if (!port->removed && port->state.linkup == linkup) - return; - - port->changed = true; -- port->linkup = linkup; -+ port->state.linkup = linkup; -+ team_refresh_port_linkup(port); - if (linkup) { - struct ethtool_cmd ecmd; - - err = __ethtool_get_settings(port->dev, &ecmd); - if (!err) { -- port->speed = ethtool_cmd_speed(&ecmd); -- port->duplex = ecmd.duplex; -+ port->state.speed = ethtool_cmd_speed(&ecmd); -+ port->state.duplex = ecmd.duplex; - goto send_event; - } - } -- port->speed = 0; -- port->duplex = 0; -+ port->state.speed = 0; -+ port->state.duplex = 0; - - send_event: - err = team_nl_send_event_port_list_get(port->team); -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 78c84fd..5fd5ab1 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -33,6 +33,24 @@ struct team_port { - struct team *team; - int index; - -+ bool linkup; /* either state.linkup or user.linkup */ -+ -+ struct { -+ bool linkup; -+ u32 speed; -+ u8 duplex; -+ } state; -+ -+ /* Values set by userspace */ -+ struct { -+ bool linkup; -+ bool linkup_enabled; -+ } user; -+ -+ /* Custom gennetlink interface related flags */ -+ bool changed; -+ bool removed; -+ - /* - * A place for storing original values of the device before it - * become a port. -@@ -42,14 +60,6 @@ struct team_port { - unsigned int mtu; - } orig; - -- bool linkup; -- u32 speed; -- u8 duplex; -- -- /* Custom gennetlink interface related flags */ -- bool changed; -- bool removed; -- - struct rcu_head rcu; - }; - diff --git a/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch b/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch deleted file mode 100644 index 13fde09c1..000000000 --- a/debian/patches/features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Jiri Pirko -Date: Tue, 10 Apr 2012 05:15:45 +0000 -Subject: [19/23] team: ab: walk through port list non-rcu - -commit 679b16073008cc536e85e2773e67234b596fb62e upstream. - -Since team->lock is being held, _rcu variant make no sense. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team_mode_activebackup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -index 6cde1ab..a715c40 100644 ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -72,7 +72,7 @@ static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx) - { - struct team_port *port; - -- list_for_each_entry_rcu(port, &team->port_list, list) { -+ list_for_each_entry(port, &team->port_list, list) { - if (port->dev->ifindex == ctx->data.u32_val) { - rcu_assign_pointer(ab_priv(team)->active_port, port); - return 0; diff --git a/debian/patches/features/all/team/0020-team-add-missed-statics.patch b/debian/patches/features/all/team/0020-team-add-missed-statics.patch deleted file mode 100644 index da5f23a29..000000000 --- a/debian/patches/features/all/team/0020-team-add-missed-statics.patch +++ /dev/null @@ -1,66 +0,0 @@ -From: Jiri Pirko -Date: Tue, 10 Apr 2012 05:15:46 +0000 -Subject: [20/23] team: add missed "statics" - -commit cade455596504fae8e134a27189713ddf7c6d04d upstream. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 2 +- - drivers/net/team/team_mode_activebackup.c | 4 ++-- - drivers/net/team/team_mode_loadbalance.c | 4 ++-- - 3 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index e639abe..153a62d 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -65,7 +65,7 @@ static int __set_port_mac(struct net_device *port_dev, - return dev_set_mac_address(port_dev, &addr); - } - --int team_port_set_orig_mac(struct team_port *port) -+static int team_port_set_orig_mac(struct team_port *port) - { - return __set_port_mac(port->dev, port->orig.dev_addr); - } -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -index a715c40..fd6bd03 100644 ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -90,12 +90,12 @@ static const struct team_option ab_options[] = { - }, - }; - --int ab_init(struct team *team) -+static int ab_init(struct team *team) - { - return team_options_register(team, ab_options, ARRAY_SIZE(ab_options)); - } - --void ab_exit(struct team *team) -+static void ab_exit(struct team *team) - { - team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options)); - } -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -index 167cdb4..2b506b2 100644 ---- a/drivers/net/team/team_mode_loadbalance.c -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -130,13 +130,13 @@ static const struct team_option lb_options[] = { - }, - }; - --int lb_init(struct team *team) -+static int lb_init(struct team *team) - { - return team_options_register(team, lb_options, - ARRAY_SIZE(lb_options)); - } - --void lb_exit(struct team *team) -+static void lb_exit(struct team *team) - { - team_options_unregister(team, lb_options, - ARRAY_SIZE(lb_options)); diff --git a/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch b/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch deleted file mode 100644 index e90a68c34..000000000 --- a/debian/patches/features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Jiri Pirko -Date: Fri, 20 Apr 2012 04:42:04 +0000 -Subject: [21/23] team: lb: let userspace care about port macs - -commit 4c78bb845bd2aaf1f7136e75314c7d034cfd120f upstream. - -Better to leave this for userspace - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team_mode_loadbalance.c | 12 ------------ - 1 file changed, 12 deletions(-) - -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -index 2b506b2..438d5b8 100644 ---- a/drivers/net/team/team_mode_loadbalance.c -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -142,22 +142,10 @@ static void lb_exit(struct team *team) - ARRAY_SIZE(lb_options)); - } - --static int lb_port_enter(struct team *team, struct team_port *port) --{ -- return team_port_set_team_mac(port); --} -- --static void lb_port_change_mac(struct team *team, struct team_port *port) --{ -- team_port_set_team_mac(port); --} -- - static const struct team_mode_ops lb_mode_ops = { - .init = lb_init, - .exit = lb_exit, - .transmit = lb_transmit, -- .port_enter = lb_port_enter, -- .port_change_mac = lb_port_change_mac, - }; - - static struct team_mode lb_mode = { diff --git a/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch b/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch deleted file mode 100644 index 8df50f7d6..000000000 --- a/debian/patches/features/all/team/0022-team-allow-to-enable-disable-ports.patch +++ /dev/null @@ -1,212 +0,0 @@ -From: Jiri Pirko -Date: Fri, 20 Apr 2012 04:42:05 +0000 -Subject: [22/23] team: allow to enable/disable ports - -commit 19a0b58e506b06fd41659d8734bba6a3e87980f4 upstream. - -This patch changes content of hashlist (used to get port struct by -computed index (0...en_port_count-1)). Now the hash list contains only -enabled ports so userspace will be able to say what ports can be used -for tx/rx. This becomes handy when userspace will need to disable ports -which does not belong to active aggregator. By default, newly added port -is enabled. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 51 ++++++++++++++++++++---------- - drivers/net/team/team_mode_loadbalance.c | 2 +- - drivers/net/team/team_mode_roundrobin.c | 2 +- - include/linux/if_team.h | 15 +++++---- - 4 files changed, 45 insertions(+), 25 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 153a62d..fe7ca40 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -559,6 +559,8 @@ static int team_change_mode(struct team *team, const char *kind) - * Rx path frame handler - ************************/ - -+static bool team_port_enabled(struct team_port *port); -+ - /* note: already called with rcu_read_lock */ - static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) - { -@@ -575,8 +577,12 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) - - port = team_port_get_rcu(skb->dev); - team = port->team; -- -- res = team->ops.receive(team, port, skb); -+ if (!team_port_enabled(port)) { -+ /* allow exact match delivery for disabled ports */ -+ res = RX_HANDLER_EXACT; -+ } else { -+ res = team->ops.receive(team, port, skb); -+ } - if (res == RX_HANDLER_ANOTHER) { - struct team_pcpu_stats *pcpu_stats; - -@@ -612,17 +618,25 @@ static bool team_port_find(const struct team *team, - return false; - } - -+static bool team_port_enabled(struct team_port *port) -+{ -+ return port->index != -1; -+} -+ - /* -- * Add/delete port to the team port list. Write guarded by rtnl_lock. -- * Takes care of correct port->index setup (might be racy). -+ * Enable/disable port by adding to enabled port hashlist and setting -+ * port->index (Might be racy so reader could see incorrect ifindex when -+ * processing a flying packet, but that is not a problem). Write guarded -+ * by team->lock. - */ --static void team_port_list_add_port(struct team *team, -- struct team_port *port) -+static void team_port_enable(struct team *team, -+ struct team_port *port) - { -- port->index = team->port_count++; -+ if (team_port_enabled(port)) -+ return; -+ port->index = team->en_port_count++; - hlist_add_head_rcu(&port->hlist, - team_port_index_hash(team, port->index)); -- list_add_tail_rcu(&port->list, &team->port_list); - } - - static void __reconstruct_port_hlist(struct team *team, int rm_index) -@@ -630,7 +644,7 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index) - int i; - struct team_port *port; - -- for (i = rm_index + 1; i < team->port_count; i++) { -+ for (i = rm_index + 1; i < team->en_port_count; i++) { - port = team_get_port_by_index(team, i); - hlist_del_rcu(&port->hlist); - port->index--; -@@ -639,15 +653,17 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index) - } - } - --static void team_port_list_del_port(struct team *team, -- struct team_port *port) -+static void team_port_disable(struct team *team, -+ struct team_port *port) - { - int rm_index = port->index; - -+ if (!team_port_enabled(port)) -+ return; - hlist_del_rcu(&port->hlist); -- list_del_rcu(&port->list); - __reconstruct_port_hlist(team, rm_index); -- team->port_count--; -+ team->en_port_count--; -+ port->index = -1; - } - - #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ -@@ -800,7 +816,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - goto err_option_port_add; - } - -- team_port_list_add_port(team, port); -+ port->index = -1; -+ team_port_enable(team, port); -+ list_add_tail_rcu(&port->list, &team->port_list); - team_adjust_ops(team); - __team_compute_features(team); - __team_port_change_check(port, !!netif_carrier_ok(port_dev)); -@@ -849,7 +867,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - - port->removed = true; - __team_port_change_check(port, false); -- team_port_list_del_port(team, port); -+ team_port_disable(team, port); -+ list_del_rcu(&port->list); - team_adjust_ops(team); - team_option_port_del(team, port); - netdev_rx_handler_unregister(port_dev); -@@ -956,7 +975,7 @@ static int team_init(struct net_device *dev) - return -ENOMEM; - - for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) -- INIT_HLIST_HEAD(&team->port_hlist[i]); -+ INIT_HLIST_HEAD(&team->en_port_hlist[i]); - INIT_LIST_HEAD(&team->port_list); - - team_adjust_ops(team); -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -index 438d5b8..86e8183 100644 ---- a/drivers/net/team/team_mode_loadbalance.c -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -38,7 +38,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) - if (unlikely(!fp)) - goto drop; - hash = SK_RUN_FILTER(fp, skb); -- port_index = hash % team->port_count; -+ port_index = hash % team->en_port_count; - port = team_get_port_by_index_rcu(team, port_index); - if (unlikely(!port)) - goto drop; -diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c -index a0e8f80..6abfbdc 100644 ---- a/drivers/net/team/team_mode_roundrobin.c -+++ b/drivers/net/team/team_mode_roundrobin.c -@@ -50,7 +50,7 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) - struct team_port *port; - int port_index; - -- port_index = rr_priv(team)->sent_packets++ % team->port_count; -+ port_index = rr_priv(team)->sent_packets++ % team->en_port_count; - port = team_get_port_by_index_rcu(team, port_index); - port = __get_first_port_up(team, port); - if (unlikely(!port)) -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 5fd5ab1..8185f57 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -28,10 +28,10 @@ struct team; - - struct team_port { - struct net_device *dev; -- struct hlist_node hlist; /* node in hash list */ -+ struct hlist_node hlist; /* node in enabled ports hash list */ - struct list_head list; /* node in ordinary list */ - struct team *team; -- int index; -+ int index; /* index of enabled port. If disabled, it's set to -1 */ - - bool linkup; /* either state.linkup or user.linkup */ - -@@ -125,11 +125,12 @@ struct team { - struct mutex lock; /* used for overall locking, e.g. port lists write */ - - /* -- * port lists with port count -+ * List of enabled ports and their count - */ -- int port_count; -- struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES]; -- struct list_head port_list; -+ int en_port_count; -+ struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; -+ -+ struct list_head port_list; /* list of all ports */ - - struct list_head option_list; - struct list_head option_inst_list; /* list of option instances */ -@@ -142,7 +143,7 @@ struct team { - static inline struct hlist_head *team_port_index_hash(struct team *team, - int port_index) - { -- return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; -+ return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; - } - - static inline struct team_port *team_get_port_by_index(struct team *team, diff --git a/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch b/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch deleted file mode 100644 index 09ef3e098..000000000 --- a/debian/patches/features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Jiri Pirko -Date: Fri, 20 Apr 2012 04:42:06 +0000 -Subject: [23/23] team: add per-port option for enabling/disabling ports - -commit acd69962341a956b5bcc5b4178b70fa527d7ce11 upstream. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller ---- - drivers/net/team/team.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index fe7ca40..c61ae35 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -904,6 +904,23 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) - return team_change_mode(team, ctx->data.str_val); - } - -+static int team_port_en_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ ctx->data.bool_val = team_port_enabled(ctx->port); -+ return 0; -+} -+ -+static int team_port_en_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ if (ctx->data.bool_val) -+ team_port_enable(team, ctx->port); -+ else -+ team_port_disable(team, ctx->port); -+ return 0; -+} -+ - static int team_user_linkup_option_get(struct team *team, - struct team_gsetter_ctx *ctx) - { -@@ -946,6 +963,13 @@ static const struct team_option team_options[] = { - .setter = team_mode_option_set, - }, - { -+ .name = "enabled", -+ .type = TEAM_OPTION_TYPE_BOOL, -+ .per_port = true, -+ .getter = team_port_en_option_get, -+ .setter = team_port_en_option_set, -+ }, -+ { - .name = "user_linkup", - .type = TEAM_OPTION_TYPE_BOOL, - .per_port = true, diff --git a/debian/patches/series b/debian/patches/series index 89b40675a..f5416fe04 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -311,33 +311,9 @@ bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch bugfix/all/fix-scsi_wait_scan.patch -features/all/define-netdev_features_t.patch -features/all/filter-Allow-to-create-sk-unattached-filters.patch - -# team driver from 3.5ish -features/all/team/0001-net-introduce-ethernet-teaming-device.patch -features/all/team/0002-team-Do-not-hold-rcu_read_lock-when-running-netlink-.patch -features/all/team/0003-team-convert-overall-spinlock-to-mutex.patch -features/all/team/0004-team-replicate-options-on-register.patch -features/all/team/0005-team-add-fix_features.patch -features/all/team/0006-team-avoid-using-variable-length-array.patch -features/all/team/0007-team-replace-kmalloc-memcpy-by-kmemdup.patch -features/all/team/0008-net-treewide-use-of-RCU_INIT_POINTER.patch -features/all/team/0009-net-introduce-vlan_vid_-add-del-and-use-them-instead.patch -features/all/team/0010-vlan-introduce-functions-to-do-mass-addition-deletio.patch -features/all/team/0011-team-use-vlan_vids_-addr-del-_by_dev.patch -features/all/team/0012-team-send-only-changed-options-ports-via-netlink.patch -features/all/team/0013-team-Stop-using-NLA_PUT.patch -features/all/team/0014-team-add-binary-option-type.patch -features/all/team/0015-team-add-loadbalance-mode.patch -features/all/team/0016-team-add-support-for-per-port-options.patch -features/all/team/0017-team-add-bool-option-type.patch -features/all/team/0018-team-add-user_linkup-and-user_linkup_enabled-per-por.patch -features/all/team/0019-team-ab-walk-through-port-list-non-rcu.patch -features/all/team/0020-team-add-missed-statics.patch -features/all/team/0021-team-lb-let-userspace-care-about-port-macs.patch -features/all/team/0022-team-allow-to-enable-disable-ports.patch -features/all/team/0023-team-add-per-port-option-for-enabling-disabling-port.patch +# netdev features, probably useful for other backports but not needed yet +#features/all/define-netdev_features_t.patch +#features/all/filter-Allow-to-create-sk-unattached-filters.patch # procfs hidepid from 3.4 features/all/hidepid/0001-procfs-parse-mount-options.patch From 57e13d1e0525fbeeaf7afea2d81a926687fe24af Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 9 Jun 2012 03:22:54 +0000 Subject: [PATCH 18/30] Avoid ABI change for hidepid svn path=/dists/sid/linux/; revision=19103 --- .../debian/avoid-ABI-change-for-hidepid.patch | 16 ++++++++++++++++ debian/patches/series | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 debian/patches/debian/avoid-ABI-change-for-hidepid.patch diff --git a/debian/patches/debian/avoid-ABI-change-for-hidepid.patch b/debian/patches/debian/avoid-ABI-change-for-hidepid.patch new file mode 100644 index 000000000..f37aa9a2d --- /dev/null +++ b/debian/patches/debian/avoid-ABI-change-for-hidepid.patch @@ -0,0 +1,16 @@ +From: Ben Hutchings +Subject: Avoid ABI change for hidepid + +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,8 +30,10 @@ + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++#ifndef __GENKSYMS__ + gid_t pid_gid; + int hide_pid; ++#endif + }; + + extern struct pid_namespace init_pid_ns; diff --git a/debian/patches/series b/debian/patches/series index f5416fe04..7f67d67de 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -320,6 +320,8 @@ features/all/hidepid/0001-procfs-parse-mount-options.patch features/all/hidepid/0002-procfs-add-hidepid-and-gid-mount-options.patch features/all/hidepid/0003-proc-fix-null-pointer-deref-in-proc_pid_permission.patch features/all/hidepid/0004-proc-fix-mount-t-proc-o-AAA.patch +# Temporary, until the next ABI bump +debian/avoid-ABI-change-for-hidepid.patch bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch From 0e35c2dc25b92ab68d5d7821d0f87c3335b5c9f8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 9 Jun 2012 17:43:22 +0000 Subject: [PATCH 19/30] Removing nvidiafb also closes #609615 svn path=/dists/sid/linux/; revision=19104 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 10fe0a60f..bde6f9a8b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,8 +13,8 @@ linux (3.2.19-2) UNRELEASED; urgency=low compliance and does not work with our current patch management * linux-image: Change package name for bugs to 'src:linux' (Closes: #644198) * DFSG: video: Remove nvidiafb and rivafb, which include apparently - obfuscated code (Closes: #383481). The nouveau driver supports all - the same hardware, aside from RIVA 128 (NV3). + obfuscated code (Closes: #383481, #609615). The nouveau driver supports + all the same hardware, aside from RIVA 128 (NV3). * udeb: Add udf-modules containing UDF filesystem module (Closes: #613972) * [mipsel/loongson2f] linux-image: Recommend libc6-loongson2f (Closes: #629410) From 1ecc86b9f22dd587cf350082d7285b8f85decee7 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Sat, 9 Jun 2012 19:20:56 +0000 Subject: [PATCH 20/30] * debian/changelog: Update. * debian/config/s390/defines, debian/config/s390x/defines: Enable debug info. svn path=/dists/sid/linux/; revision=19109 --- debian/changelog | 3 +++ debian/config/s390/defines | 3 +++ debian/config/s390x/defines | 3 +++ 3 files changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index bde6f9a8b..efad323ba 100644 --- a/debian/changelog +++ b/debian/changelog @@ -28,6 +28,9 @@ linux (3.2.19-2) UNRELEASED; urgency=low * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE (Closes: #676360) + [ Bastian Blank ] + * [s390/s390x,s390x/s390x] Build debugging symbols. + -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 linux-2.6 (3.2.19-1) unstable; urgency=low diff --git a/debian/config/s390/defines b/debian/config/s390/defines index 222bca46d..6fe38f5ba 100644 --- a/debian/config/s390/defines +++ b/debian/config/s390/defines @@ -33,6 +33,9 @@ initramfs: false override-localversion: s390 type: plain-s390-tape +[s390x_build] +debug-info: true + [s390x_description] hardware: IBM zSeries parts: reader diff --git a/debian/config/s390x/defines b/debian/config/s390x/defines index 7adbe89ec..8a968b75d 100644 --- a/debian/config/s390x/defines +++ b/debian/config/s390x/defines @@ -18,6 +18,9 @@ part-short-tape: IPL from tape bootloaders: s390-tools configs: s390/config +[s390x_build] +debug-info: true + [s390x_description] hardware: IBM zSeries parts: reader From d5fa98077e83448fe31eec2f457883928c399997 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 10 Jun 2012 02:14:51 +0000 Subject: [PATCH 21/30] linux-source: Add single patch for each featureset svn path=/dists/sid/linux/; revision=19114 --- debian/changelog | 1 + debian/lib/python/debian_linux/gencontrol.py | 2 ++ debian/rules.real | 33 ++++++++++++++------ debian/templates/control.source.in | 2 +- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/debian/changelog b/debian/changelog index efad323ba..168e100ad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -27,6 +27,7 @@ linux (3.2.19-2) UNRELEASED; urgency=low * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE (Closes: #676360) + * linux-source: Add single patch for each featureset [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/lib/python/debian_linux/gencontrol.py b/debian/lib/python/debian_linux/gencontrol.py index 389af7027..b10dfadba 100644 --- a/debian/lib/python/debian_linux/gencontrol.py +++ b/debian/lib/python/debian_linux/gencontrol.py @@ -114,6 +114,8 @@ class Gencontrol(object): pass def do_main_makefile(self, makefile, makeflags, extra): + makeflags = makeflags.copy() + makeflags['ALL_FEATURESETS'] = ' '.join(self.config['base', ]['featuresets']) makefile.add('binary-indep', cmds=["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags]) def do_main_packages(self, packages, vars, makeflags, extra): diff --git a/debian/rules.real b/debian/rules.real index d2915a890..ead7b8e8c 100644 --- a/debian/rules.real +++ b/debian/rules.real @@ -73,6 +73,16 @@ $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: $(STAMPS_DIR)/source cd '$(BUILD_DIR)'; tar -cjf 'linux-source-$(UPSTREAMVERSION).tar.bz2' 'linux-source-$(UPSTREAMVERSION)' rm -rf '$(DIR)' +$(BUILD_DIR)/linux-patch-$(UPSTREAMVERSION)-%.patch.bz2: $(STAMPS_DIR)/source_none $(STAMPS_DIR)/source_% + set -o pipefail; \ + (cd '$(BUILD_DIR)'; \ + set +e; \ + diff -urN -p -x debian -x .pc -x .svk -x .svn source_none source_$*; \ + test $$? -eq 1) | \ + filterdiff --remove-timestamps --strip=1 --addoldprefix=a/ --addnewprefix=b/ | \ + bzip2 -c >$@ || \ + (rm -f $@; exit 1) + define patch_cmd cd '$(DIR)' && QUILT_PATCHES='$(CURDIR)/debian/patches' QUILT_SERIES=series-$(1) quilt push --quiltrc - -a -q --fuzz=0 endef @@ -82,17 +92,20 @@ $(STAMPS_DIR)/source: set +e; quilt unapplied --quiltrc - >/dev/null && echo 'Patch series not fully applied'; test $$? -eq 1 @$(stamp) -$(STAMPS_DIR)/source_$(FEATURESET): SOURCE_DIR=$(BUILD_DIR)/source -$(STAMPS_DIR)/source_$(FEATURESET): DIR=$(BUILD_DIR)/source_$(FEATURESET) -$(STAMPS_DIR)/source_$(FEATURESET): $(STAMPS_DIR)/source +$(STAMPS_DIR)/source_%: SOURCE_DIR=$(BUILD_DIR)/source +$(STAMPS_DIR)/source_%: DIR=$(BUILD_DIR)/source_$* +$(STAMPS_DIR)/source_%: $(STAMPS_DIR)/source mkdir -p '$(BUILD_DIR)' rm -rf '$(DIR)' -ifeq ($(FEATURESET),none) - ln -s '$(CURDIR)' '$(DIR)' -else $(call copy_source,$(DIR)) - $(call patch_cmd,$(FEATURESET)) -endif + $(call patch_cmd,$*) + @$(stamp) +.PRECIOUS: $(STAMPS_DIR)/source_% + +$(STAMPS_DIR)/source_none: DIR=$(BUILD_DIR)/source_none +$(STAMPS_DIR)/source_none: $(STAMPS_DIR)/source + rm -f '$(DIR)' + ln -s '$(CURDIR)' '$(DIR)' @$(stamp) $(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): CONFIG=$(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR) @@ -474,10 +487,10 @@ install-udeb_$(ARCH): dh_builddeb install-source: DH_OPTIONS = -plinux-source-$(VERSION) -install-source: $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2 +install-source: $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2 $(foreach FEATURESET,$(filter-out none,$(ALL_FEATURESETS)),$(BUILD_DIR)/linux-patch-$(UPSTREAMVERSION)-$(FEATURESET).patch.bz2) dh_testdir dh_testroot - dh_install '$<' /usr/src + dh_install '$^' /usr/src +$(MAKE_SELF) install-base # vim: filetype=make diff --git a/debian/templates/control.source.in b/debian/templates/control.source.in index 8bc6b65e3..e1161eedf 100644 --- a/debian/templates/control.source.in +++ b/debian/templates/control.source.in @@ -3,7 +3,7 @@ Priority: optional Maintainer: Debian Kernel Team Uploaders: Bastian Blank , Frederik Schüler , maximilian attems , Ben Hutchings Standards-Version: 3.9.2 -Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.84), quilt +Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.6.6-3~), lzma [armel], kernel-wedge (>= 2.84), quilt, patchutils Build-Depends-Indep: bzip2, xmlto Vcs-Svn: svn://svn.debian.org/svn/kernel/dists/trunk/linux/ Vcs-Browser: http://anonscm.debian.org/viewvc/kernel/dists/trunk/linux/ From af8a298fdf2af7da99161d754605ffb563434e62 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 10 Jun 2012 02:19:02 +0000 Subject: [PATCH 22/30] Restore a necessary mkdir dropped by the previous change svn path=/dists/sid/linux/; revision=19115 --- debian/rules.real | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules.real b/debian/rules.real index ead7b8e8c..1b4dcf741 100644 --- a/debian/rules.real +++ b/debian/rules.real @@ -104,6 +104,7 @@ $(STAMPS_DIR)/source_%: $(STAMPS_DIR)/source $(STAMPS_DIR)/source_none: DIR=$(BUILD_DIR)/source_none $(STAMPS_DIR)/source_none: $(STAMPS_DIR)/source + mkdir -p '$(BUILD_DIR)' rm -f '$(DIR)' ln -s '$(CURDIR)' '$(DIR)' @$(stamp) From 0be791d98b9b0b5d711d4f65c044de0c9f5330e4 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 10 Jun 2012 15:30:24 +0000 Subject: [PATCH 23/30] Update to 3.2.20 svn path=/dists/sid/linux/; revision=19116 --- debian/changelog | 2 +- ...fresh-the-sysfs-files-when-pertinent.patch | 49 ------ .../drm-i915-Disable-FBC-on-SandyBridge.patch | 32 ---- .../bugfix/all/fix-scsi_wait_scan.patch | 40 ----- ...etlb-fix-resv_map-leak-in-error-path.patch | 95 ----------- .../mm-fix-vma_resv_map-null-pointer.patch | 66 -------- .../arm/ARM-ixp4xx-gpiolib-support.patch | 158 ------------------ ...estore-skb_set_dev-removed-in-3.2.20.patch | 17 ++ debian/patches/series | 10 +- 9 files changed, 19 insertions(+), 450 deletions(-) delete mode 100644 debian/patches/bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch delete mode 100644 debian/patches/bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch delete mode 100644 debian/patches/bugfix/all/fix-scsi_wait_scan.patch delete mode 100644 debian/patches/bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch delete mode 100644 debian/patches/bugfix/all/mm-fix-vma_resv_map-null-pointer.patch delete mode 100644 debian/patches/bugfix/arm/ARM-ixp4xx-gpiolib-support.patch create mode 100644 debian/patches/debian/net-restore-skb_set_dev-removed-in-3.2.20.patch diff --git a/debian/changelog b/debian/changelog index 168e100ad..472fda13f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -linux (3.2.19-2) UNRELEASED; urgency=low +linux (3.2.20-1) UNRELEASED; urgency=low * The "Confused? You Won't Be" release diff --git a/debian/patches/bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch b/debian/patches/bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch deleted file mode 100644 index 90659142b..000000000 --- a/debian/patches/bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Andy Whitcroft -Date: Thu, 3 May 2012 14:48:26 +0100 -Subject: ACPI battery: only refresh the sysfs files when pertinent - information changes - -commit c5971456964290da7e98222892797b71ef793e62 upstream. - -We only need to regenerate the sysfs files when the capacity units -change, avoid the update otherwise. - -The origin of this issue is dates way back to 2.6.38: -da8aeb92d4853f37e281f11fddf61f9c7d84c3cd -(ACPI / Battery: Update information on info notification and resume) - -Signed-off-by: Andy Whitcroft -Tested-by: Ralf Jung -Signed-off-by: Len Brown ---- - drivers/acpi/battery.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c -index 86933ca..7dd3f9f 100644 ---- a/drivers/acpi/battery.c -+++ b/drivers/acpi/battery.c -@@ -643,11 +643,19 @@ static int acpi_battery_update(struct acpi_battery *battery) - - static void acpi_battery_refresh(struct acpi_battery *battery) - { -+ int power_unit; -+ - if (!battery->bat.dev) - return; - -+ power_unit = battery->power_unit; -+ - acpi_battery_get_info(battery); -- /* The battery may have changed its reporting units. */ -+ -+ if (power_unit == battery->power_unit) -+ return; -+ -+ /* The battery has changed its reporting units. */ - sysfs_remove_battery(battery); - sysfs_add_battery(battery); - } --- -1.7.10 - diff --git a/debian/patches/bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch b/debian/patches/bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch deleted file mode 100644 index a05704fe8..000000000 --- a/debian/patches/bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Chris Wilson -Date: Tue, 8 Nov 2011 23:17:34 +0000 -Subject: [PATCH] drm/i915:: Disable FBC on SandyBridge - -commit d56d8b28e9247e7e35e02fbb12b12239a2c33ad1 upstream. - -Enabling FBC is causing the BLT ring to run between 10-100x slower than -normal and frequently lockup. The interim solution is disable FBC once -more until we know why. - -Signed-off-by: Chris Wilson -Signed-off-by: Keith Packard ---- - drivers/gpu/drm/i915/intel_display.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index b3b51c4..19f35ec 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -1872,7 +1872,7 @@ static void intel_update_fbc(struct drm_device *dev) - if (enable_fbc < 0) { - DRM_DEBUG_KMS("fbc set to per-chip default\n"); - enable_fbc = 1; -- if (INTEL_INFO(dev)->gen <= 5) -+ if (INTEL_INFO(dev)->gen <= 6) - enable_fbc = 0; - } - if (!enable_fbc) { --- -1.7.10 - diff --git a/debian/patches/bugfix/all/fix-scsi_wait_scan.patch b/debian/patches/bugfix/all/fix-scsi_wait_scan.patch deleted file mode 100644 index aee0bce6e..000000000 --- a/debian/patches/bugfix/all/fix-scsi_wait_scan.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: James Bottomley -Date: Wed, 30 May 2012 09:45:39 +0000 -Subject: [SCSI] fix scsi_wait_scan - -commit 1ff2f40305772b159a91c19590ee159d3a504afc upstream. - -Commit c751085943362143f84346d274e0011419c84202 -Author: Rafael J. Wysocki -Date: Sun Apr 12 20:06:56 2009 +0200 - - PM/Hibernate: Wait for SCSI devices scan to complete during resume - -Broke the scsi_wait_scan module in 2.6.30. Apparently debian still uses it so -fix it and backport to stable before removing it in 3.6. - -The breakage is caused because the function template in -include/scsi/scsi_scan.h is defined to be a nop unless SCSI is built in. -That means that in the modular case (which is every distro), the -scsi_wait_scan module does a simple async_synchronize_full() instead of -waiting for scans. - -Signed-off-by: James Bottomley -Signed-off-by: Ben Hutchings ---- - drivers/scsi/scsi_wait_scan.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c -index 74708fc..ae78148 100644 ---- a/drivers/scsi/scsi_wait_scan.c -+++ b/drivers/scsi/scsi_wait_scan.c -@@ -12,7 +12,7 @@ - - #include - #include --#include -+#include "scsi_priv.h" - - static int __init wait_scan_init(void) - { diff --git a/debian/patches/bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch b/debian/patches/bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch deleted file mode 100644 index 2ea5e1c81..000000000 --- a/debian/patches/bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch +++ /dev/null @@ -1,95 +0,0 @@ -From: Dave Hansen -Date: Fri, 18 May 2012 11:46:30 -0700 -Subject: hugetlb: fix resv_map leak in error path - -commit c50ac050811d6485616a193eb0f37bfbd191cc89 upstream. - -When called for anonymous (non-shared) mappings, hugetlb_reserve_pages() -does a resv_map_alloc(). It depends on code in hugetlbfs's -vm_ops->close() to release that allocation. - -However, in the mmap() failure path, we do a plain unmap_region() without -the remove_vma() which actually calls vm_ops->close(). - -This is a decent fix. This leak could get reintroduced if new code (say, -after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return -an error. But, I think it would have to unroll the reservation anyway. - -Christoph's test case: - - http://marc.info/?l=linux-mm&m=133728900729735 - -Signed-off-by: Dave Hansen -[Christoph Lameter: I have rediffed the patch against 2.6.32 and 3.2.0.] -Signed-off-by: Ben Hutchings ---- - mm/hugetlb.c | 28 ++++++++++++++++++++++------ - 1 file changed, 22 insertions(+), 6 deletions(-) - ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -2068,6 +2068,15 @@ - kref_get(&reservations->refs); - } - -+static void resv_map_put(struct vm_area_struct *vma) -+{ -+ struct resv_map *reservations = vma_resv_map(vma); -+ -+ if (!reservations) -+ return; -+ kref_put(&reservations->refs, resv_map_release); -+} -+ - static void hugetlb_vm_op_close(struct vm_area_struct *vma) - { - struct hstate *h = hstate_vma(vma); -@@ -2083,7 +2092,7 @@ - reserve = (end - start) - - region_count(&reservations->regions, start, end); - -- kref_put(&reservations->refs, resv_map_release); -+ resv_map_put(vma); - - if (reserve) { - hugetlb_acct_memory(h, -reserve); -@@ -2884,12 +2893,16 @@ - set_vma_resv_flags(vma, HPAGE_RESV_OWNER); - } - -- if (chg < 0) -- return chg; -+ if (chg < 0) { -+ ret = chg; -+ goto out_err; -+ } - - /* There must be enough filesystem quota for the mapping */ -- if (hugetlb_get_quota(inode->i_mapping, chg)) -- return -ENOSPC; -+ if (hugetlb_get_quota(inode->i_mapping, chg)) { -+ ret = -ENOSPC; -+ goto out_err; -+ } - - /* - * Check enough hugepages are available for the reservation. -@@ -2898,7 +2911,7 @@ - ret = hugetlb_acct_memory(h, chg); - if (ret < 0) { - hugetlb_put_quota(inode->i_mapping, chg); -- return ret; -+ goto out_err; - } - - /* -@@ -2915,6 +2928,9 @@ - if (!vma || vma->vm_flags & VM_MAYSHARE) - region_add(&inode->i_mapping->private_list, from, to); - return 0; -+out_err: -+ resv_map_put(vma); -+ return ret; - } - - void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) diff --git a/debian/patches/bugfix/all/mm-fix-vma_resv_map-null-pointer.patch b/debian/patches/bugfix/all/mm-fix-vma_resv_map-null-pointer.patch deleted file mode 100644 index d6c0c3974..000000000 --- a/debian/patches/bugfix/all/mm-fix-vma_resv_map-null-pointer.patch +++ /dev/null @@ -1,66 +0,0 @@ -From: Dave Hansen -Date: Wed, 30 May 2012 07:51:07 -0700 -Subject: mm: fix vma_resv_map() NULL pointer - -commit 4523e1458566a0e8ecfaff90f380dd23acc44d27 upstream. - -hugetlb_reserve_pages() can be used for either normal file-backed -hugetlbfs mappings, or MAP_HUGETLB. In the MAP_HUGETLB, semi-anonymous -mode, there is not a VMA around. The new call to resv_map_put() assumed -that there was, and resulted in a NULL pointer dereference: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 - IP: vma_resv_map+0x9/0x30 - PGD 141453067 PUD 1421e1067 PMD 0 - Oops: 0000 [#1] PREEMPT SMP - ... - Pid: 14006, comm: trinity-child6 Not tainted 3.4.0+ #36 - RIP: vma_resv_map+0x9/0x30 - ... - Process trinity-child6 (pid: 14006, threadinfo ffff8801414e0000, task ffff8801414f26b0) - Call Trace: - resv_map_put+0xe/0x40 - hugetlb_reserve_pages+0xa6/0x1d0 - hugetlb_file_setup+0x102/0x2c0 - newseg+0x115/0x360 - ipcget+0x1ce/0x310 - sys_shmget+0x5a/0x60 - system_call_fastpath+0x16/0x1b - -This was reported by Dave Jones, but was reproducible with the -libhugetlbfs test cases, so shame on me for not running them in the -first place. - -With this, the oops is gone, and the output of libhugetlbfs's -run_tests.py is identical to plain 3.4 again. - -[ Marked for stable, since this was introduced by commit c50ac050811d - ("hugetlb: fix resv_map leak in error path") which was also marked for - stable ] - -Reported-by: Dave Jones -Cc: Mel Gorman -Cc: KOSAKI Motohiro -Cc: Christoph Lameter -Cc: Andrea Arcangeli -Cc: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Ben Hutchings ---- - mm/hugetlb.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 285a81e..e198831 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -3036,7 +3036,8 @@ int hugetlb_reserve_pages(struct inode *inode, - region_add(&inode->i_mapping->private_list, from, to); - return 0; - out_err: -- resv_map_put(vma); -+ if (vma) -+ resv_map_put(vma); - return ret; - } - diff --git a/debian/patches/bugfix/arm/ARM-ixp4xx-gpiolib-support.patch b/debian/patches/bugfix/arm/ARM-ixp4xx-gpiolib-support.patch deleted file mode 100644 index 33bce6104..000000000 --- a/debian/patches/bugfix/arm/ARM-ixp4xx-gpiolib-support.patch +++ /dev/null @@ -1,158 +0,0 @@ -From: Imre Kaloz -Subject: [RFC/PATCH] ARM: ixp4xx gpiolib support -Date: Mon, 5 Sep 2011 14:49:51 +0200 - -This patch adds gpiolib support for the IXP4xx platform - -Signed-off-by: Imre Kaloz ---- - arch/arm/Kconfig | 2 +- - arch/arm/mach-ixp4xx/common.c | 39 +++++++++++++++++++++++++ - arch/arm/mach-ixp4xx/include/mach/gpio.h | 46 ++++++++++-------------------- - 3 files changed, 55 insertions(+), 32 deletions(-) - -Index: source_armel_none/arch/arm/Kconfig -=================================================================== ---- source_armel_none.orig/arch/arm/Kconfig 2012-01-07 20:47:15.000000000 +0100 -+++ source_armel_none/arch/arm/Kconfig 2012-01-07 20:51:00.390593917 +0100 -@@ -520,7 +520,7 @@ config ARCH_IXP4XX - depends on MMU - select CLKSRC_MMIO - select CPU_XSCALE -- select GENERIC_GPIO -+ select ARCH_REQUIRE_GPIOLIB - select GENERIC_CLOCKEVENTS - select HAVE_SCHED_CLOCK - select MIGHT_HAVE_PCI -Index: source_armel_none/arch/arm/mach-ixp4xx/common.c -=================================================================== ---- source_armel_none.orig/arch/arm/mach-ixp4xx/common.c 2012-01-07 20:47:15.000000000 +0100 -+++ source_armel_none/arch/arm/mach-ixp4xx/common.c 2012-01-07 20:51:00.390593917 +0100 -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -376,12 +377,50 @@ static struct platform_device *ixp46x_de - unsigned long ixp4xx_exp_bus_size; - EXPORT_SYMBOL(ixp4xx_exp_bus_size); - -+static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) -+{ -+ gpio_line_config(gpio, IXP4XX_GPIO_IN); -+ return 0; -+} -+ -+static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) -+{ -+ gpio_line_set(gpio, level); -+ gpio_line_config(gpio, IXP4XX_GPIO_OUT); -+ return 0; -+} -+ -+static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) -+{ -+ int value; -+ -+ gpio_line_get(gpio, &value); -+ return value; -+} -+ -+static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) -+{ -+ gpio_line_set(gpio, value); -+} -+ -+static struct gpio_chip ixp4xx_gpio_chip = { -+ .label = "IXP4XX_GPIO_CHIP", -+ .direction_input = ixp4xx_gpio_direction_input, -+ .direction_output = ixp4xx_gpio_direction_output, -+ .get = ixp4xx_gpio_get_value, -+ .set = ixp4xx_gpio_set_value, -+ .base = 0, -+ .ngpio = 16, -+}; -+ - void __init ixp4xx_sys_init(void) - { - ixp4xx_exp_bus_size = SZ_16M; - - platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); - -+ gpiochip_add(&ixp4xx_gpio_chip); -+ - if (cpu_is_ixp46x()) { - int region; - -Index: source_armel_none/arch/arm/mach-ixp4xx/include/mach/gpio.h -=================================================================== ---- source_armel_none.orig/arch/arm/mach-ixp4xx/include/mach/gpio.h 2012-01-07 20:47:15.000000000 +0100 -+++ source_armel_none/arch/arm/mach-ixp4xx/include/mach/gpio.h 2012-01-07 20:51:00.390593917 +0100 -@@ -27,49 +27,33 @@ - - #include - #include -+#include /* cansleep wrappers */ - - #define __ARM_GPIOLIB_COMPLEX - --static inline int gpio_request(unsigned gpio, const char *label) --{ -- return 0; --} -- --static inline void gpio_free(unsigned gpio) --{ -- might_sleep(); -- -- return; --} -- --static inline int gpio_direction_input(unsigned gpio) --{ -- gpio_line_config(gpio, IXP4XX_GPIO_IN); -- return 0; --} -- --static inline int gpio_direction_output(unsigned gpio, int level) --{ -- gpio_line_set(gpio, level); -- gpio_line_config(gpio, IXP4XX_GPIO_OUT); -- return 0; --} -+#define NR_BUILTIN_GPIO 16 - - static inline int gpio_get_value(unsigned gpio) - { -- int value; -- -- gpio_line_get(gpio, &value); -- -- return value; -+ if (gpio < NR_BUILTIN_GPIO) -+ { -+ int value; -+ gpio_line_get(gpio, &value); -+ return value; -+ } -+ else -+ return __gpio_get_value(gpio); - } - - static inline void gpio_set_value(unsigned gpio, int value) - { -- gpio_line_set(gpio, value); -+ if (gpio < NR_BUILTIN_GPIO) -+ gpio_line_set(gpio, value); -+ else -+ __gpio_set_value(gpio, value); - } - --#include /* cansleep wrappers */ -+#define gpio_cansleep __gpio_cansleep - - extern int gpio_to_irq(int gpio); - #define gpio_to_irq gpio_to_irq diff --git a/debian/patches/debian/net-restore-skb_set_dev-removed-in-3.2.20.patch b/debian/patches/debian/net-restore-skb_set_dev-removed-in-3.2.20.patch new file mode 100644 index 000000000..f1f014eee --- /dev/null +++ b/debian/patches/debian/net-restore-skb_set_dev-removed-in-3.2.20.patch @@ -0,0 +1,17 @@ +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1869,6 +1869,14 @@ + } + EXPORT_SYMBOL(netif_device_attach); + ++/* This function was a bad idea and was removed in 3.2.20 */ ++void skb_set_dev(struct sk_buff *skb, struct net_device *dev) ++{ ++ WARN_ON_ONCE(!net_eq(dev_net(skb->dev), dev_net(dev))); ++ skb->dev = dev; ++} ++EXPORT_SYMBOL(skb_set_dev); ++ + /* + * Invalidate hardware checksum when packet is to be mangled, and + * complete checksum manually on outgoing path. diff --git a/debian/patches/series b/debian/patches/series index 7f67d67de..88ca4c341 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -53,7 +53,6 @@ bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch debian/x86-memtest-WARN-if-bad-RAM-found.patch bugfix/all/snapshot-Implement-compat_ioctl.patch debian/ARM-Remove-use-of-possibly-undefined-BUILD_BUG_ON-in.patch -bugfix/arm/ARM-ixp4xx-gpiolib-support.patch bugfix/arm/ARM-topdown-mmap.patch bugfix/alpha/alpha-add-io-read-write-16-32-be-functions.patch features/arm/ARM-kirkwood-6282A1.patch @@ -190,6 +189,7 @@ debian/skbuff-avoid-ABI-change-in-3.2.17.patch debian/usb-hcd-avoid-ABI-change-in-3.2.17.patch debian/fork-avoid-ABI-change-in-3.2.18.patch debian/mmc-Avoid-ABI-change-in-3.2.19.patch +debian/net-restore-skb_set_dev-removed-in-3.2.20.patch bugfix/all/ext4-Report-max_batch_time-option-correctly.patch @@ -224,8 +224,6 @@ features/all/wacom/0026-Input-wacom-return-proper-error-if-usb_get_extra_des.pat features/all/rt2x00-add-debug-message-for-new-chipset.patch features/all/rt2x00-add-rt5372-chipset-support.patch -bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch - # Update be2net driver to 3.5ish features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch @@ -298,19 +296,13 @@ features/all/codel/0005-net-codel-fix-build-errors.patch features/all/codel/0006-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch features/all/codel/0007-fq_codel-should-use-qdisc-backlog-as-threshold.patch -bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch - # AppArmor userland compatibility. This had better be gone in wheezy+1! features/all/AppArmor-compatibility-patch-for-v5-interface.patch bugfix/x86/mm-pmd_read_atomic-fix-32bit-pae-pmd-walk-vs-pmd_populate-smp-race.patch bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch -bugfix/all/hugetlb-fix-resv_map-leak-in-error-path.patch -bugfix/all/mm-fix-vma_resv_map-null-pointer.patch bugfix/all/hugepages-fix-use-after-free-bug-in-quota-handling.patch -bugfix/all/fix-scsi_wait_scan.patch - # netdev features, probably useful for other backports but not needed yet #features/all/define-netdev_features_t.patch #features/all/filter-Allow-to-create-sk-unattached-filters.patch From 148d3c9049cc630de3ba835904c72002a41ec1b1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 10 Jun 2012 23:54:15 +0000 Subject: [PATCH 24/30] [x86] Enable CRASH_DUMP, PROC_VMCORE (Closes: #623177) svn path=/dists/sid/linux/; revision=19117 --- debian/changelog | 1 + debian/config/kernelarch-x86/config | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 472fda13f..0d06ac822 100644 --- a/debian/changelog +++ b/debian/changelog @@ -28,6 +28,7 @@ linux (3.2.20-1) UNRELEASED; urgency=low * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE (Closes: #676360) * linux-source: Add single patch for each featureset + * [x86] Enable CRASH_DUMP, PROC_VMCORE (Closes: #623177) [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/config/kernelarch-x86/config b/debian/config/kernelarch-x86/config index fc53108ba..d80bd8bcf 100644 --- a/debian/config/kernelarch-x86/config +++ b/debian/config/kernelarch-x86/config @@ -48,7 +48,7 @@ CONFIG_EFI_STUB=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y CONFIG_KEXEC=y -# CONFIG_CRASH_DUMP is not set +CONFIG_CRASH_DUMP=y # CONFIG_KEXEC_JUMP is not set CONFIG_RELOCATABLE=y CONFIG_HOTPLUG_CPU=y @@ -1570,6 +1570,11 @@ CONFIG_SGI_PARTITION=y CONFIG_ULTRIX_PARTITION=y CONFIG_SUN_PARTITION=y +## +## file: fs/proc/Kconfig +## +CONFIG_PROC_VMCORE=y + ## ## file: kernel/irq/Kconfig ## From 05124b51aa6a0e8ae619bbe2e7568840e3c12016 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 00:05:38 +0000 Subject: [PATCH 25/30] media/dvb: Enable DVB_DDBRIDGE as module (Closes: #676952) svn path=/dists/sid/linux/; revision=19118 --- debian/changelog | 1 + debian/config/config | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 0d06ac822..f7c2b1663 100644 --- a/debian/changelog +++ b/debian/changelog @@ -29,6 +29,7 @@ linux (3.2.20-1) UNRELEASED; urgency=low (Closes: #676360) * linux-source: Add single patch for each featureset * [x86] Enable CRASH_DUMP, PROC_VMCORE (Closes: #623177) + * media/dvb: Enable DVB_DDBRIDGE as module (Closes: #676952) [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/config/config b/debian/config/config index 001ffd8d0..4ef3eef82 100644 --- a/debian/config/config +++ b/debian/config/config @@ -947,6 +947,11 @@ CONFIG_DVB_B2C2_FLEXCOP_USB=m ## CONFIG_DVB_BT8XX=m +## +## file: drivers/media/dvb/ddbridge/Kconfig +## +CONFIG_DVB_DDBRIDGE=m + ## ## file: drivers/media/dvb/dm1105/Kconfig ## From 423985846ce3be9ebef0dade785336577cca4038 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 00:50:22 +0000 Subject: [PATCH 26/30] Summarise the upstream stable update svn path=/dists/sid/linux/; revision=19119 --- debian/changelog | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/debian/changelog b/debian/changelog index f7c2b1663..0dbb5e74c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,25 @@ linux (3.2.20-1) UNRELEASED; urgency=low * The "Confused? You Won't Be" release + * New upstream stable update: + http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.20 + - cifs: fix oops while traversing open file list (try #4) + - mm/fork: fix overflow in vma length when copying mmap on clone + - mm: fix faulty initialization in vmalloc_init() + - x86, amd, xen: Avoid NULL pointer paravirt references + - ext4: force ro mount if ext4_setup_super() fails + - ext4: disallow hard-linked directory in ext4_lookup + - ext4: add missing save_error_info() to ext4_error() + - ALSA: usb-audio: fix rate_list memory leak + - Bluetooth: btusb: typo in Broadcom SoftSailing id (Closes: #674565) + - ipv4: Do not use dead fib_info entries. + - ipv4: fix the rcu race between free_fib_info and ip_route_output_slow + - l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case + - btree: fix tree corruption in btree_get_prev() + - asix: allow full size 8021Q frames to be received (Closes: #676545) + - ext4: don't trash state flags in EXT4_IOC_SETFLAGS + - ext4: fix the free blocks calculation for ext3 file systems w/ uninit_bg + [ Ben Hutchings ] * Rename source package to 'linux' (Closes: #636010) * Convert source package format to 3.0 (quilt) From e86e382c7531829b8366ed225c053784d0ec2c0d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 01:14:36 +0000 Subject: [PATCH 27/30] net: sock: validate data_len before allocating skb in sock_alloc_send_pskb() (CVE-2012-2136) svn path=/dists/sid/linux/; revision=19120 --- debian/changelog | 2 + ...e-data_len-before-allocating-skb-in-.patch | 48 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 51 insertions(+) create mode 100644 debian/patches/bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch diff --git a/debian/changelog b/debian/changelog index 0dbb5e74c..1897afeb2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -49,6 +49,8 @@ linux (3.2.20-1) UNRELEASED; urgency=low * linux-source: Add single patch for each featureset * [x86] Enable CRASH_DUMP, PROC_VMCORE (Closes: #623177) * media/dvb: Enable DVB_DDBRIDGE as module (Closes: #676952) + * net: sock: validate data_len before allocating skb in + sock_alloc_send_pskb() (CVE-2012-2136) [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/patches/bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch b/debian/patches/bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch new file mode 100644 index 000000000..86b0554bc --- /dev/null +++ b/debian/patches/bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch @@ -0,0 +1,48 @@ +From: Jason Wang +Date: Wed, 30 May 2012 21:18:10 +0000 +Subject: net: sock: validate data_len before allocating skb in + sock_alloc_send_pskb() + +commit cc9b17ad29ecaa20bfe426a8d4dbfb94b13ff1cc upstream. + +We need to validate the number of pages consumed by data_len, otherwise frags +array could be overflowed by userspace. So this patch validate data_len and +return -EMSGSIZE when data_len may occupies more frags than MAX_SKB_FRAGS. + +Signed-off-by: Jason Wang +Signed-off-by: David S. Miller +--- + net/core/sock.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 653f8c0..9e5b71f 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1592,6 +1592,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, + gfp_t gfp_mask; + long timeo; + int err; ++ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; ++ ++ err = -EMSGSIZE; ++ if (npages > MAX_SKB_FRAGS) ++ goto failure; + + gfp_mask = sk->sk_allocation; + if (gfp_mask & __GFP_WAIT) +@@ -1610,14 +1615,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, + if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { + skb = alloc_skb(header_len, gfp_mask); + if (skb) { +- int npages; + int i; + + /* No pages, we're done... */ + if (!data_len) + break; + +- npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + skb->truesize += data_len; + skb_shinfo(skb)->nr_frags = npages; + for (i = 0; i < npages; i++) { diff --git a/debian/patches/series b/debian/patches/series index 88ca4c341..27fa4d5cf 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -317,3 +317,4 @@ debian/avoid-ABI-change-for-hidepid.patch bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch From d6260419d9e8d4d041effcc1a7c47ec4226019a2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 01:40:02 +0000 Subject: [PATCH 28/30] Fix CVE-2012-2119 and other critical bugs in macvtap zerocopy svn path=/dists/sid/linux/; revision=19121 --- debian/changelog | 6 ++ ...-fix-offset-calculation-when-buildin.patch | 61 +++++++++++++++ ...erocopy-fix-truesize-underestimation.patch | 41 ++++++++++ ...-put-page-when-fail-to-get-all-reque.patch | 35 +++++++++ ...-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch | 48 ++++++++++++ ...-validate-vectors-before-building-sk.patch | 78 +++++++++++++++++++ debian/patches/series | 6 ++ 7 files changed, 275 insertions(+) create mode 100644 debian/patches/bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch create mode 100644 debian/patches/bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch create mode 100644 debian/patches/bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch create mode 100644 debian/patches/bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch create mode 100644 debian/patches/bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch diff --git a/debian/changelog b/debian/changelog index 1897afeb2..6de4d61f4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -51,6 +51,12 @@ linux (3.2.20-1) UNRELEASED; urgency=low * media/dvb: Enable DVB_DDBRIDGE as module (Closes: #676952) * net: sock: validate data_len before allocating skb in sock_alloc_send_pskb() (CVE-2012-2136) + * macvtap: zerocopy: fix offset calculation when building skb + * macvtap: zerocopy: fix truesize underestimation + * macvtap: zerocopy: put page when fail to get all requested user pages + * macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is built + successfully + * macvtap: zerocopy: validate vectors before building skb (CVE-2012-2119) [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/patches/bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch b/debian/patches/bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch new file mode 100644 index 000000000..911076814 --- /dev/null +++ b/debian/patches/bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch @@ -0,0 +1,61 @@ +From: Jason Wang +Date: Wed, 2 May 2012 11:41:30 +0800 +Subject: [1/5] macvtap: zerocopy: fix offset calculation when building skb + +commit 3afc9621f15701c557e60f61eba9242bac2771dd upstream. + +This patch fixes the offset calculation when building skb: + +- offset1 were used as skb data offset not vector offset +- reset offset to zero only when we advance to next vector + +Signed-off-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/net/macvtap.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 0427c65..bd4a70d 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -505,10 +505,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + if (copy > size) { + ++from; + --count; +- } ++ offset = 0; ++ } else ++ offset += size; + copy -= size; + offset1 += size; +- offset = 0; + } + + if (len == offset1) +@@ -519,13 +520,13 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + int num_pages; + unsigned long base; + +- len = from->iov_len - offset1; ++ len = from->iov_len - offset; + if (!len) { +- offset1 = 0; ++ offset = 0; + ++from; + continue; + } +- base = (unsigned long)from->iov_base + offset1; ++ base = (unsigned long)from->iov_base + offset; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + num_pages = get_user_pages_fast(base, size, 0, &page[i]); + if ((num_pages != size) || +@@ -546,7 +547,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + len -= size; + i++; + } +- offset1 = 0; ++ offset = 0; + ++from; + } + return 0; diff --git a/debian/patches/bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch b/debian/patches/bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch new file mode 100644 index 000000000..75164f0a2 --- /dev/null +++ b/debian/patches/bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch @@ -0,0 +1,41 @@ +From: Jason Wang +Date: Wed, 2 May 2012 11:41:44 +0800 +Subject: [2/5] macvtap: zerocopy: fix truesize underestimation + +commit 4ef67ebedffa44ed9939b34708ac2fee06d2f65f upstream. + +As the skb fragment were pinned/built from user pages, we should +account the page instead of length for truesize. + +Signed-off-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/net/macvtap.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index bd4a70d..7cb2684 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -519,6 +519,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + struct page *page[MAX_SKB_FRAGS]; + int num_pages; + unsigned long base; ++ unsigned long truesize; + + len = from->iov_len - offset; + if (!len) { +@@ -533,10 +534,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) + /* put_page is in skb free */ + return -EFAULT; ++ truesize = size * PAGE_SIZE; + skb->data_len += len; + skb->len += len; +- skb->truesize += len; +- atomic_add(len, &skb->sk->sk_wmem_alloc); ++ skb->truesize += truesize; ++ atomic_add(truesize, &skb->sk->sk_wmem_alloc); + while (len) { + int off = base & ~PAGE_MASK; + int size = min_t(int, len, PAGE_SIZE - off); diff --git a/debian/patches/bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch b/debian/patches/bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch new file mode 100644 index 000000000..1674eb84f --- /dev/null +++ b/debian/patches/bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch @@ -0,0 +1,35 @@ +From: Jason Wang +Date: Wed, 2 May 2012 11:41:58 +0800 +Subject: [3/5] macvtap: zerocopy: put page when fail to get all requested + user pages + +commit 02ce04bb3d28c3333231f43bca677228dbc686fe upstream. + +When get_user_pages_fast() fails to get all requested pages, we could not use +kfree_skb() to free it as it has not been put in the skb fragments. So we need +to call put_page() instead. + +Signed-off-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/net/macvtap.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 7cb2684..9ab182a 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -531,9 +531,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + num_pages = get_user_pages_fast(base, size, 0, &page[i]); + if ((num_pages != size) || +- (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) +- /* put_page is in skb free */ ++ (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) { ++ for (i = 0; i < num_pages; i++) ++ put_page(page[i]); + return -EFAULT; ++ } + truesize = size * PAGE_SIZE; + skb->data_len += len; + skb->len += len; diff --git a/debian/patches/bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch b/debian/patches/bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch new file mode 100644 index 000000000..fb5c20256 --- /dev/null +++ b/debian/patches/bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch @@ -0,0 +1,48 @@ +From: Jason Wang +Date: Wed, 2 May 2012 11:42:06 +0800 +Subject: [4/5] macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is + built successfully + +commit 01d6657b388438def19c8baaea28e742b6ed32ec upstream. + +Current the SKBTX_DEV_ZEROCOPY is set unconditionally after +zerocopy_sg_from_iovec(), this would lead NULL pointer when macvtap +fails to build zerocopy skb because destructor_arg was not +initialized. Solve this by set this flag after the skb were built +successfully. + +Signed-off-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/net/macvtap.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 9ab182a..a4ff694 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -699,10 +699,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + if (!skb) + goto err; + +- if (zerocopy) { ++ if (zerocopy) + err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); +- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; +- } else ++ else + err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, + len); + if (err) +@@ -721,8 +720,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + rcu_read_lock_bh(); + vlan = rcu_dereference_bh(q->vlan); + /* copy skb_ubuf_info for callback when skb has no error */ +- if (zerocopy) ++ if (zerocopy) { + skb_shinfo(skb)->destructor_arg = m->msg_control; ++ skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; ++ } + if (vlan) + macvlan_start_xmit(skb, vlan->dev); + else diff --git a/debian/patches/bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch b/debian/patches/bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch new file mode 100644 index 000000000..b9f8ce82c --- /dev/null +++ b/debian/patches/bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch @@ -0,0 +1,78 @@ +From: Jason Wang +Date: Wed, 2 May 2012 11:42:15 +0800 +Subject: macvtap: zerocopy: validate vectors before building skb + +commit b92946e2919134ebe2a4083e4302236295ea2a73 upstream. + +There're several reasons that the vectors need to be validated: + +- Return error when caller provides vectors whose num is greater than UIO_MAXIOV. +- Linearize part of skb when userspace provides vectors grater than MAX_SKB_FRAGS. +- Return error when userspace provides vectors whose total length may exceed +- MAX_SKB_FRAGS * PAGE_SIZE. + +Signed-off-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/net/macvtap.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index a4ff694..163559c 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -529,9 +529,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + } + base = (unsigned long)from->iov_base + offset; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; ++ if (i + size > MAX_SKB_FRAGS) ++ return -EMSGSIZE; + num_pages = get_user_pages_fast(base, size, 0, &page[i]); +- if ((num_pages != size) || +- (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) { ++ if (num_pages != size) { + for (i = 0; i < num_pages; i++) + put_page(page[i]); + return -EFAULT; +@@ -651,7 +652,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + int err; + struct virtio_net_hdr vnet_hdr = { 0 }; + int vnet_hdr_len = 0; +- int copylen; ++ int copylen = 0; + bool zerocopy = false; + + if (q->flags & IFF_VNET_HDR) { +@@ -680,15 +681,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + if (unlikely(len < ETH_HLEN)) + goto err; + ++ err = -EMSGSIZE; ++ if (unlikely(count > UIO_MAXIOV)) ++ goto err; ++ + if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) + zerocopy = true; + + if (zerocopy) { ++ /* Userspace may produce vectors with count greater than ++ * MAX_SKB_FRAGS, so we need to linearize parts of the skb ++ * to let the rest of data to be fit in the frags. ++ */ ++ if (count > MAX_SKB_FRAGS) { ++ copylen = iov_length(iv, count - MAX_SKB_FRAGS); ++ if (copylen < vnet_hdr_len) ++ copylen = 0; ++ else ++ copylen -= vnet_hdr_len; ++ } + /* There are 256 bytes to be copied in skb, so there is enough + * room for skb expand head in case it is used. + * The rest buffer is mapped from userspace. + */ +- copylen = vnet_hdr.hdr_len; ++ if (copylen < vnet_hdr.hdr_len) ++ copylen = vnet_hdr.hdr_len; + if (!copylen) + copylen = GOODCOPY_LEN; + } else diff --git a/debian/patches/series b/debian/patches/series index 27fa4d5cf..420d198cf 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -318,3 +318,9 @@ debian/avoid-ABI-change-for-hidepid.patch bugfix/all/NFSv4-Reduce-the-footprint-of-the-idmapper.patch bugfix/all/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch + +bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch +bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch +bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch +bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch +bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch From 412108cbfe16dd8c7c7cf0039cab594a0731bb3b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 01:45:24 +0000 Subject: [PATCH 29/30] KVM: Fix buffer overflow in kvm_set_irq() (CVE-2012-2137) svn path=/dists/sid/linux/; revision=19122 --- debian/changelog | 1 + ...M-Fix-buffer-overflow-in-kvm_set_irq.patch | 33 +++++++++++++++++++ debian/patches/series | 2 ++ 3 files changed, 36 insertions(+) create mode 100644 debian/patches/bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch diff --git a/debian/changelog b/debian/changelog index 6de4d61f4..59a4947b6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -57,6 +57,7 @@ linux (3.2.20-1) UNRELEASED; urgency=low * macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is built successfully * macvtap: zerocopy: validate vectors before building skb (CVE-2012-2119) + * KVM: Fix buffer overflow in kvm_set_irq() (CVE-2012-2137) [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. diff --git a/debian/patches/bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch b/debian/patches/bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch new file mode 100644 index 000000000..08d4368d0 --- /dev/null +++ b/debian/patches/bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch @@ -0,0 +1,33 @@ +From: Avi Kivity +Date: Sun, 22 Apr 2012 17:02:11 +0300 +Subject: [PATCH] KVM: Fix buffer overflow in kvm_set_irq() + +commit f2ebd422f71cda9c791f76f85d2ca102ae34a1ed upstream. + +kvm_set_irq() has an internal buffer of three irq routing entries, allowing +connecting a GSI to three IRQ chips or on MSI. However setup_routing_entry() +does not properly enforce this, allowing three irqchip routes followed by +an MSI route to overflow the buffer. + +Fix by ensuring that an MSI entry is added to an empty list. + +Signed-off-by: Avi Kivity +--- + virt/kvm/irq_comm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c +index a6a0365..5afb431 100644 +--- a/virt/kvm/irq_comm.c ++++ b/virt/kvm/irq_comm.c +@@ -332,6 +332,7 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt, + */ + hlist_for_each_entry(ei, n, &rt->map[ue->gsi], link) + if (ei->type == KVM_IRQ_ROUTING_MSI || ++ ue->type == KVM_IRQ_ROUTING_MSI || + ue->u.irqchip.irqchip == ei->irqchip.irqchip) + return r; + +-- +1.7.10 + diff --git a/debian/patches/series b/debian/patches/series index 420d198cf..85f31202d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -324,3 +324,5 @@ bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch + +bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch From c216062874049e69905e6a0e7000af28a4f714db Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 11 Jun 2012 04:07:03 +0000 Subject: [PATCH 30/30] Prepare to release linux (3.2.20-1). svn path=/dists/sid/linux/; revision=19123 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 59a4947b6..3ccb7987f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -linux (3.2.20-1) UNRELEASED; urgency=low +linux (3.2.20-1) unstable; urgency=low * The "Confused? You Won't Be" release @@ -62,7 +62,7 @@ linux (3.2.20-1) UNRELEASED; urgency=low [ Bastian Blank ] * [s390/s390x,s390x/s390x] Build debugging symbols. - -- Ben Hutchings Sat, 02 Jun 2012 20:31:53 +0100 + -- Ben Hutchings Mon, 11 Jun 2012 02:46:34 +0100 linux-2.6 (3.2.19-1) unstable; urgency=low