Rebase to Linux 3.3-rc1

The utrace patch is left unapplied as it doesn't apply cleanly any longer
This commit is contained in:
Josh Boyer 2012-01-20 13:32:57 -05:00
parent 0a621ccdd4
commit e8409b1dce
35 changed files with 269 additions and 4576 deletions

View File

@ -1,42 +0,0 @@
From c0190925dacd976a67044f4382d4effbed568dce Mon Sep 17 00:00:00 2001
From: Jesse Sung <jesse.sung@canonical.com>
Date: Thu, 22 Dec 2011 10:48:47 +0800
Subject: [PATCH] Bluetooth: Add support for BCM20702A0 [0a5c:21e3]
Add another vendor specific ID for BCM20702A0.
output of usb-devices:
T: Bus=06 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0a5c ProdID=21e3 Rev=01.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=9439E5CBF66C
C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
drivers/bluetooth/btusb.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index a67c6db..fbfba80 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -101,6 +101,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x413c, 0x8197) },
{ } /* Terminating entry */
--
1.7.6.2

View File

@ -7,15 +7,7 @@
**** Queued for 3.3 ***********************************************************************************
drm-edid-try-harder-to-fix-up-broken-headers.patch
Bluetooth-Add-support-for-BCM20702A0-0a5c-21e3.patch
ext4-Support-check-none-nocheck-mount-options.patch
ext4-Fix-error-handling-on-inode-bitmap-corruption.patch
proc-clean-up-and-fix-proc-pid-mem-handling.patch
proc-fix-null-pointer-deref-in-proc_pid_permission.patch
procfs-add-hidepid-and-gid-mount-options.patch
procfs-parse-mount-options.patch
epoll-limit-paths.patch
Unused-iocbs-in-a-batch-should-not-be-accounted-as-a.patch
**** Other stuff that should go upstream (in decreasing likelyhood) ************************************

View File

@ -1,68 +0,0 @@
From 69e4747ee9727d660b88d7e1efe0f4afcb35db1b Mon Sep 17 00:00:00 2001
From: Gleb Natapov <gleb@redhat.com>
Date: Sun, 8 Jan 2012 17:07:28 +0200
Subject: [PATCH] Unused iocbs in a batch should not be accounted as active.
Since commit 080d676de095 ("aio: allocate kiocbs in batches") iocbs are
allocated in a batch during processing of first iocbs. All iocbs in a
batch are automatically added to ctx->active_reqs list and accounted in
ctx->reqs_active.
If one (not the last one) of iocbs submitted by an user fails, further
iocbs are not processed, but they are still present in ctx->active_reqs
and accounted in ctx->reqs_active. This causes process to stuck in a D
state in wait_for_all_aios() on exit since ctx->reqs_active will never
go down to zero. Furthermore since kiocb_batch_free() frees iocb
without removing it from active_reqs list the list become corrupted
which may cause oops.
Fix this by removing iocb from ctx->active_reqs and updating
ctx->reqs_active in kiocb_batch_free().
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
Cc: stable@kernel.org # 3.2
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
fs/aio.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index 78c514c..969beb0 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -476,14 +476,21 @@ static void kiocb_batch_init(struct kiocb_batch *batch, long total)
batch->count = total;
}
-static void kiocb_batch_free(struct kiocb_batch *batch)
+static void kiocb_batch_free(struct kioctx *ctx, struct kiocb_batch *batch)
{
struct kiocb *req, *n;
+ if (list_empty(&batch->head))
+ return;
+
+ spin_lock_irq(&ctx->ctx_lock);
list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
list_del(&req->ki_batch);
+ list_del(&req->ki_list);
kmem_cache_free(kiocb_cachep, req);
+ ctx->reqs_active--;
}
+ spin_unlock_irq(&ctx->ctx_lock);
}
/*
@@ -1742,7 +1749,7 @@ long do_io_submit(aio_context_t ctx_id, long nr,
}
blk_finish_plug(&plug);
- kiocb_batch_free(&batch);
+ kiocb_batch_free(ctx, &batch);
put_ioctx(ctx);
return i ? i : ret;
}
--
1.7.7.5

1861
alps.patch

File diff suppressed because it is too large Load Diff

View File

@ -22,14 +22,15 @@ diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/
{ 0, },
};
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig
--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500
+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500
@@ -5,7 +5,6 @@ config BRCMSMAC
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index cd6375d..caa0302 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -4,7 +4,6 @@ config BRCMUTIL
config BRCMSMAC
tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
depends on PCI
depends on MAC80211
- depends on BCMA=n
- depends on BCMA
select BRCMUTIL
select FW_LOADER
select CRC_CCITT

View File

@ -1,131 +0,0 @@
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -265,7 +265,6 @@ int rtl92c_download_fw(struct ieee80211_
if (!rtlhal->pfirmware)
return 1;
- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
pfwdata = (u8 *) rtlhal->pfirmware;
fwsize = rtlhal->fwsize;
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
rtlpriv->rtlhal.fwsize = firmware->size;
release_firmware(firmware);
+ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name);
return 0;
}
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -43,6 +43,8 @@
#include "hw.h"
#include <linux/vmalloc.h>
#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/types.h>
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
MODULE_AUTHOR("Ziv Huang <ziv_huang@realtek.com>");
@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
+static char *rtl8192cu_firmware; /* pointer to firmware */
+static int firmware_size;
+static atomic_t usage_count;
+
static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i
rtlpriv->dm.disable_framebursting = false;
rtlpriv->dm.thermalvalue = 0;
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
- if (!rtlpriv->rtlhal.pfirmware) {
+
+ if (rtl8192cu_firmware) {
+ /* firmware already loaded - true for suspend/resume
+ * and multiple instances of the device */
+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware;
+ rtlpriv->rtlhal.fwsize = firmware_size;
+ return 0;
+ }
+ rtl8192cu_firmware = vzalloc(0x4000);
+ if (!rtl8192cu_firmware) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Can't alloc buffer for fw.\n"));
return 1;
}
+
/* request fw */
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
rtlpriv->io.dev);
@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i
release_firmware(firmware);
return 1;
}
- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+ pr_info("rtl8192cu: Loaded firmware from file %s\n",
+ rtlpriv->cfg->fw_name);
+ memcpy(rtl8192cu_firmware, firmware->data, firmware->size);
+ firmware_size = firmware->size;
rtlpriv->rtlhal.fwsize = firmware->size;
+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware;
release_firmware(firmware);
+ atomic_inc(&usage_count);
return 0;
}
@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- if (rtlpriv->rtlhal.pfirmware) {
- vfree(rtlpriv->rtlhal.pfirmware);
+ atomic_dec(&usage_count);
+ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) {
+ vfree(rtl8192cu_firmware);
+ rtl8192cu_firmware = NULL;
rtlpriv->rtlhal.pfirmware = NULL;
}
}
+#ifdef CONFIG_PM_SLEEP
+static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf,
+ pm_message_t message)
+{
+ /* Increase usage_count to Save loaded fw across suspend/resume */
+ atomic_inc(&usage_count);
+ return 0;
+}
+
+static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf)
+{
+ atomic_dec(&usage_count); /* after resume, decrease usage count */
+ return 0;
+}
+#endif
+
static struct rtl_hal_ops rtl8192cu_hal_ops = {
.init_sw_vars = rtl92cu_init_sw_vars,
.deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive
.disconnect = rtl_usb_disconnect,
.id_table = rtl8192c_usb_ids,
-#ifdef CONFIG_PM
- /* .suspend = rtl_usb_suspend, */
- /* .resume = rtl_usb_resume, */
- /* .reset_resume = rtl8192c_resume, */
-#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_SLEEP
+ .suspend = rtl8192cu_usb_suspend,
+ .resume = rtl8192cu_usb_resume,
+#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_AUTOSUSPEND
.supports_autosuspend = 1,
#endif

View File

@ -200,3 +200,4 @@ CONFIG_ARM_ERRATA_751472=y
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_CS89x0 is not set
# CONFIG_OF_SELFTEST is not set

View File

@ -96,3 +96,9 @@ CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_PL310_ERRATA_769419=y
CONFIG_LEDS_RENESAS_TPU=y
# CONFIG_ARM_LPAE is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set

View File

@ -40,3 +40,7 @@ CONFIG_RTC_DRV_MV=m
CONFIG_MV_XOR=y
CONFIG_CRYPTO_DEV_MV_CESA=m
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set

View File

@ -1083,3 +1083,19 @@ CONFIG_LEDS_RENESAS_TPU=y
# CONFIG_OMAP_IOMMU is not set
CONFIG_USB_RENESAS_USBHS_HCD=m
# CONFIG_ARM_LPAE is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set
# CONFIG_SOC_OMAPTI81XX is not set
# CONFIG_SOC_OMAPAM33XX is not set
# CONFIG_MACH_TI8148EVM is not set
# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
# CONFIG_MICREL_KS8995MA is not set
# CONFIG_CHARGER_MANAGER is not set
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_DA9052_I2C is not set
# CONFIG_MFD_S5M_CORE is not set
# CONFIG_VIDEO_AS3645A is not set
#

View File

@ -90,3 +90,15 @@ CONFIG_ARM_CPU_TOPOLOGY=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_LEDS_RENESAS_TPU=y
# CONFIG_ARCH_TEGRA_2x_SOC is not set
# CONFIG_ARCH_TEGRA_3x_SOC is not set
# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
# CONFIG_ETHERNET is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set
# CONFIG_DVB_TDA1004X is not set
# CONFIG_DVB_PLL is not set
# CONFIG_SND_SOC_TEGRA_ALC5632 is not set

View File

@ -149,6 +149,7 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y
CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
CONFIG_INFINIBAND_IPOIB_CM=y
CONFIG_INFINIBAND_SRP=m
CONFIG_INFINIBAND_SRPT=m
CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_IPATH=m
@ -248,6 +249,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_OSD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
@ -648,12 +650,14 @@ CONFIG_TCP_MD5SIG=y
#
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=m
CONFIG_NET_KEY=m
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
CONFIG_INET_LRO=y
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
@ -702,6 +706,12 @@ CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
#
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_PE_SIP=m
@ -744,6 +754,7 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NF_CONNTRACK=m
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_TPROXY=m
@ -784,6 +795,7 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ECN=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
@ -795,6 +807,7 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
CONFIG_NETFILTER_XT_MATCH_OSF=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
@ -824,6 +837,7 @@ CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NF_CONNTRACK_PROCFS=y # check if contrack(8) in f17 supports netlink
# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
@ -847,6 +861,7 @@ CONFIG_NF_CT_PROTO_UDPLITE=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_RPFILTER=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
@ -879,6 +894,7 @@ CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RPFILTER=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_QUEUE=m
@ -1040,6 +1056,9 @@ CONFIG_NET_ACT_SIMP=m
CONFIG_NET_ACT_SKBEDIT=m
CONFIG_DCB=y
# CONFIG_OPENVSWITCH is not set
CONFIG_NETPRIO_CGROUP=m
#
# Network testing
@ -1056,6 +1075,9 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
CONFIG_IFB=m
CONFIG_NET_TEAM=m
CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
CONFIG_DUMMY=m
CONFIG_BONDING=m
CONFIG_MACVLAN=m
@ -1143,6 +1165,7 @@ CONFIG_ATL1E=m
CONFIG_NET_VENDOR_BROCADE=y
CONFIG_BNA=m
CONFIG_NET_CALXEDA_XGMAC=m
CONFIG_NET_VENDOR_CHELSIO=y
CONFIG_CHELSIO_T1=m
@ -1275,6 +1298,8 @@ CONFIG_SMSC9420=m
CONFIG_NET_VENDOR_STMICRO=y
CONFIG_STMMAC_ETH=m
# CONFIG_STMMAC_PLATFORM is not set
# CONFIG_STMMAC_PCI is not set
# CONFIG_STMMAC_DA is not set
# CONFIG_STMMAC_DUAL_MAC is not set
# CONFIG_STMMAC_TIMER is not set
@ -1424,6 +1449,7 @@ CONFIG_ATH9K_AHB=y
# CONFIG_ATH9K_DEBUG is not set
CONFIG_ATH9K_DEBUGFS=y
CONFIG_ATH9K_HTC=m
CONFIG_ATH9K_BTCOEX_SUPPORT=y
# CONFIG_ATH9K_HTC_DEBUGFS is not set
CONFIG_ATH9K_RATE_CONTROL=y
CONFIG_CARL9170=m
@ -1452,6 +1478,7 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
# CONFIG_B43LEGACY_PIO_MODE is not set
CONFIG_BRCMSMAC=m
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_SDIO=y
# CONFIG_BRCMDBG is not set
CONFIG_HERMES=m
CONFIG_HERMES_CACHE_FW_ON_INIT=y
@ -1485,11 +1512,10 @@ CONFIG_IWLWIFI=m
CONFIG_IWLWIFI_DEBUG=y
CONFIG_IWLWIFI_DEBUGFS=y
CONFIG_IWLWIFI_DEVICE_SVTOOL=y
# CONFIG_IWL_P2P is not set
CONFIG_IWLAGN=m
CONFIG_IWLWIFI_LEGACY=m
CONFIG_IWLWIFI_LEGACY_DEBUG=y
CONFIG_IWLWIFI_LEGACY_DEBUGFS=y
# CONFIG_IWLWIFI_P2P is not set
CONFIG_IWLEGACY=m
CONFIG_IWLEGACY_DEBUG=y
CONFIG_IWLEGACY_DEBUGFS=y
# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set
CONFIG_IWL4965=y
CONFIG_IWL3945=m
@ -1869,8 +1895,10 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_QT1070 is not set
# CONFIG_KEYBOARD_MCS is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_SAMSUNG is not set
# CONFIG_KEYBOARD_QT2160 is not set
# CONFIG_KEYBOARD_TCA6416 is not set
# CONFIG_KEYBOARD_TCA8418 is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@ -1919,6 +1947,7 @@ CONFIG_TOUCHSCREEN_AD7879_I2C=m
# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
CONFIG_TOUCHSCREEN_DYNAPRO=m
CONFIG_TOUCHSCREEN_EETI=m
CONFIG_TOUCHSCREEN_EGALAX=m
CONFIG_TOUCHSCREEN_ELO=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GUNZE=m
@ -1934,6 +1963,7 @@ CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_TOUCHIT213=m
CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_PIXCIR=m
CONFIG_TOUCHSCREEN_UCB1400=m
CONFIG_TOUCHSCREEN_WACOM_W8001=m
CONFIG_TOUCHSCREEN_USB_E2I=y
@ -2421,6 +2451,7 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
#
CONFIG_V4L_USB_DRIVERS=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
CONFIG_V4L_PCI_DRIVERS=y
CONFIG_VIDEO_AU0828=m
CONFIG_VIDEO_BT848=m
CONFIG_VIDEO_BT848_DVB=y
@ -2471,6 +2502,8 @@ CONFIG_VIDEO_ZORAN_DC30=m
CONFIG_VIDEO_ZORAN_LML33=m
CONFIG_VIDEO_ZORAN_LML33R10=m
CONFIG_VIDEO_ZORAN_ZR36060=m
# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_VIDEO_FB_IVTV=m
CONFIG_VIDEO_SAA7164=m
CONFIG_VIDEO_TM6000=m
@ -2498,6 +2531,7 @@ CONFIG_MEDIA_TUNER_TEA5761=m
CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_MT2060=m
CONFIG_MEDIA_TUNER_MT2063=m
CONFIG_MEDIA_TUNER_MT2266=m
CONFIG_MEDIA_TUNER_MT2131=m
CONFIG_MEDIA_TUNER_QT1010=m
@ -2621,6 +2655,7 @@ CONFIG_DVB_DDBRIDGE=m
CONFIG_DVB_MB86A20S=m
CONFIG_DVB_USB_TECHNISAT_USB2=m
CONFIG_DVB_DIB9000=m
CONFIG_DVB_HD29L2=m
CONFIG_DVB_STV0367=m
#
@ -2696,6 +2731,7 @@ CONFIG_IR_RC6_DECODER=m
CONFIG_IR_JVC_DECODER=m
CONFIG_IR_SONY_DECODER=m
CONFIG_IR_RC5_SZ_DECODER=m
CONFIG_IR_SANYO_DECODER=m
CONFIG_IR_MCE_KBD_DECODER=m
CONFIG_IR_LIRC_CODEC=m
CONFIG_IR_IMON=m
@ -2996,6 +3032,7 @@ CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_EHCI_MV is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_HCD_SSB is not set
CONFIG_USB_UHCI_HCD=y
@ -3101,11 +3138,13 @@ CONFIG_HID_ACRUX_FF=y
CONFIG_HID_KEYTOUCH=m
CONFIG_HID_LCPOWER=m
CONFIG_HID_ROCCAT_ARVO=m
CONFIG_HID_ROCCAT_ISKU=m
CONFIG_HID_ROCCAT_KOVAPLUS=m
CONFIG_HID_HOLTEK=m
CONFIG_HOLTEK_FF=y
CONFIG_HID_SPEEDLINK=m
CONFIG_HID_WIIMOTE=m
CONFIG_HID_WIIMOTE_EXT=y
#
# USB Imaging devices
@ -3157,6 +3196,7 @@ CONFIG_USB_GSPCA_PAC7302=m
CONFIG_USB_GSPCA_STV0680=m
CONFIG_USB_GL860=m
CONFIG_USB_GSPCA_JEILINJ=m
CONFIG_USB_GSPCA_JL2005BCD=m
CONFIG_USB_GSPCA_KONICA=m
CONFIG_USB_GSPCA_XIRLINK_CIT=m
CONFIG_USB_GSPCA_SPCA1528=m
@ -3547,6 +3587,8 @@ CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
# Maybe see if we want this on for debug kernels?
# CONFIG_NFSD_FAULT_INJECTION is not set
CONFIG_NFS_FSCACHE=y
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_NFS_USE_NEW_IDMAPPER=y
@ -3593,6 +3635,8 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
# Maybe see if we want this on for debug kernels?
# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
CONFIG_CONFIGFS_FS=y
@ -3764,6 +3808,7 @@ CONFIG_SECURITY_SELINUX_AVC_STATS=y
# CONFIG_SECURITY_APPARMOR is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set
#
# Cryptographic options
@ -3902,6 +3947,7 @@ CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount'
# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set
CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y
CONFIG_CGROUP_PERF=y
CONFIG_BLK_CGROUP=y
@ -3986,6 +4032,7 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_S3C24XX is not set
CONFIG_LEDS_DELL_NETBOOKS=m
# CONFIG_LEDS_TCA6507 is not set
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_IDE_DISK=y
@ -4059,6 +4106,7 @@ CONFIG_APM_POWER=m
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_BATTERY_DS2782 is not set
# CONFIG_BATTERY_SBS is not set
# CONFIG_BATTERY_BQ20Z75 is not set
# CONFIG_BATTERY_DS2780 is not set
# CONFIG_BATTERY_BQ27x00 is not set
@ -4067,6 +4115,7 @@ CONFIG_APM_POWER=m
# CONFIG_CHARGER_ISP1704 is not set
# CONFIG_CHARGER_MAX8903 is not set
# CONFIG_CHARGER_LP8727 is not set
# CONFIG_CHARGER_GPIO is not set
# CONFIG_CHARGER_PCF50633 is not set
@ -4169,6 +4218,8 @@ CONFIG_UWB_WHCI=m
CONFIG_UWB_I1480U=m
CONFIG_STAGING=y
# CONFIG_RTLLIB is not set
# CONFIG_ANDROID is not set
# CONFIG_STAGING_MEDIA is not set
# CONFIG_ET131X is not set
# CONFIG_SLICOSS is not set

View File

@ -352,3 +352,11 @@ CONFIG_RFKILL_GPIO=m
# Disable btrfs until it is shown to work with 64k pages (rhbz 747079)
# CONFIG_BTRFS_FS is not set
#
# CONFIG_CPU_IDLE is not set
# CONFIG_OF_SELFTEST is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set
CONFIG_STRICT_DEVMEM=y

View File

@ -158,3 +158,7 @@ CONFIG_IO_EVENT_IRQ=y
CONFIG_HW_RANDOM_AMD=m
CONFIG_BPF_JIT=y
# CONFIG_PPC_ICSWX_PID is not set
# CONFIG_PPC_ICSWX_USE_SIGILL is not set
# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set

View File

@ -195,3 +195,4 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y
# CONFIG_MTD_OF_PARTS is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MMC_SDHCI_OF is not set
# CONFIG_OF_SELFTEST is not set

View File

@ -201,3 +201,7 @@ CONFIG_I2O_BUS=m
# CONFIG_EDAC_SBRIDGE is not set
# CONFIG_X86_WANT_INTEL_MID is not set
# CONFIG_OF_SELFTEST is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_INPUT_GP2A is not set
# CONFIG_INPUT_GPIO_TILT_POLLED is not set

View File

@ -34,6 +34,7 @@ CONFIG_X86_PAT=y
CONFIG_X86_PM_TIMER=y
CONFIG_EFI=y
# CONFIG_EFI_STUB is not set
CONFIG_EFI_VARS=y
CONFIG_EFI_PCDP=y
CONFIG_FB_EFI=y
@ -113,6 +114,7 @@ CONFIG_PM_STD_PARTITION=""
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_IOAPIC=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_COMPAQ=m
@ -216,6 +218,7 @@ CONFIG_XO15_EBOOK=m
# CONFIG_SMSC37B787_WDT is not set
CONFIG_W83697HF_WDT=m
CONFIG_VIA_WDT=m
CONFIG_CRASH_DUMP=y
CONFIG_PROC_VMCORE=y
@ -375,6 +378,7 @@ CONFIG_PCH_PHUB=m
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CRYPTO_AES_NI_INTEL=y
CONFIG_CRYPTO_SERPENT_SSE2_586=m
CONFIG_HP_ACCEL=m
@ -389,3 +393,12 @@ CONFIG_RELOCATABLE=y
# CONFIG_HYPERV is not set
# Depends on HOTPLUG_PCI_PCIE
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
# Figure out how this relates to DRM_PSB in staging because confused
# CONFIG_DRM_GMA500 is not set
# Maybe enable in debug kernels?
# CONFIG_DEBUG_NMI_SELFTEST is not set

View File

@ -11,6 +11,7 @@ CONFIG_K8_NUMA=y
CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
# CONFIG_NUMA_EMU is not set
# CONFIG_X86_NUMACHIP is not set
CONFIG_NR_CPUS=64
CONFIG_PHYSICAL_START=0x1000000
@ -20,6 +21,7 @@ CONFIG_IA32_EMULATION=y
CONFIG_AMD_IOMMU=y
CONFIG_AMD_IOMMU_STATS=y
CONFIG_AMD_IOMMU_V2=m
# CONFIG_IOMMU_DEBUG is not set
CONFIG_SWIOTLB=y
# CONFIG_CALGARY_IOMMU is not set
@ -35,6 +37,7 @@ CONFIG_ACPI_HOTPLUG_MEMORY=m
CONFIG_HOTPLUG_PCI_SHPC=m
CONFIG_CRYPTO_AES_X86_64=y
CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m
CONFIG_CRYPTO_TWOFISH_X86_64=m
CONFIG_CRYPTO_SALSA20_X86_64=m
CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m

View File

@ -1,465 +0,0 @@
From 0a6cc45426fe3baaf231efd7efe4300fd879efc8 Mon Sep 17 00:00:00 2001
From: Jason Baron <jbaron@redhat.com>
Date: Mon, 24 Oct 2011 14:59:02 +1100
Subject: [PATCH] epoll: limit paths
epoll: limit paths
The current epoll code can be tickled to run basically indefinitely in
both loop detection path check (on ep_insert()), and in the wakeup paths.
The programs that tickle this behavior set up deeply linked networks of
epoll file descriptors that cause the epoll algorithms to traverse them
indefinitely. A couple of these sample programs have been previously
posted in this thread: https://lkml.org/lkml/2011/2/25/297.
To fix the loop detection path check algorithms, I simply keep track of
the epoll nodes that have been already visited. Thus, the loop detection
becomes proportional to the number of epoll file descriptor and links.
This dramatically decreases the run-time of the loop check algorithm. In
one diabolical case I tried it reduced the run-time from 15 mintues (all
in kernel time) to .3 seconds.
Fixing the wakeup paths could be done at wakeup time in a similar manner
by keeping track of nodes that have already been visited, but the
complexity is harder, since there can be multiple wakeups on different
cpus...Thus, I've opted to limit the number of possible wakeup paths when
the paths are created.
This is accomplished, by noting that the end file descriptor points that
are found during the loop detection pass (from the newly added link), are
actually the sources for wakeup events. I keep a list of these file
descriptors and limit the number and length of these paths that emanate
from these 'source file descriptors'. In the current implemetation I
allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of
length 4 and 10 of length 5. Note that it is sufficient to check the
'source file descriptors' reachable from the newly added link, since no
other 'source file descriptors' will have newly added links. This allows
us to check only the wakeup paths that may have gotten too long, and not
re-check all possible wakeup paths on the system.
In terms of the path limit selection, I think its first worth noting that
the most common case for epoll, is probably the model where you have 1
epoll file descriptor that is monitoring n number of 'source file
descriptors'. In this case, each 'source file descriptor' has a 1 path of
length 1. Thus, I believe that the limits I'm proposing are quite
reasonable and in fact may be too generous. Thus, I'm hoping that the
proposed limits will not prevent any workloads that currently work to
fail.
In terms of locking, I have extended the use of the 'epmutex' to all
epoll_ctl add and remove operations. Currently its only used in a subset
of the add paths. I need to hold the epmutex, so that we can correctly
traverse a coherent graph, to check the number of paths. I believe that
this additional locking is probably ok, since its in the setup/teardown
paths, and doesn't affect the running paths, but it certainly is going to
add some extra overhead. Also, worth noting is that the epmuex was
recently added to the ep_ctl add operations in the initial path loop
detection code using the argument that it was not on a critical path.
Another thing to note here, is the length of epoll chains that is allowed.
Currently, eventpoll.c defines:
/* Maximum number of nesting allowed inside epoll sets */
#define EP_MAX_NESTS 4
This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS
+ 1). However, this limit is currently only enforced during the loop
check detection code, and only when the epoll file descriptors are added
in a certain order. Thus, this limit is currently easily bypassed. The
newly added check for wakeup paths, stricly limits the wakeup paths to a
length of 5, regardless of the order in which ep's are linked together.
Thus, a side-effect of the new code is a more consistent enforcement of
the graph depth.
Thus far, I've tested this, using the sample programs previously
mentioned, which now either return quickly or return -EINVAL. I've also
testing using the piptest.c epoll tester, which showed no difference in
performance. I've also created a number of different epoll networks and
tested that they behave as expectded.
I believe this solves the original diabolical test cases, while still
preserving the sane epoll nesting.
Signed-off-by: Jason Baron <jbaron@redhat.com>
Cc: Nelson Elhage <nelhage@ksplice.com>
Cc: Davide Libenzi <davidel@xmailserver.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++-----
include/linux/eventpoll.h | 1 +
include/linux/fs.h | 1 +
3 files changed, 203 insertions(+), 25 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index b84fad9..414ac74 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -197,6 +197,12 @@ struct eventpoll {
/* The user that created the eventpoll descriptor */
struct user_struct *user;
+
+ struct file *file;
+
+ /* used to optimize loop detection check */
+ int visited;
+ struct list_head visitedllink;
};
/* Wait structure used by the poll hooks */
@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly;
/* Slab cache used to allocate "struct eppoll_entry" */
static struct kmem_cache *pwq_cache __read_mostly;
+/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
+LIST_HEAD(visited_list);
+
+/* Files with newly added links, which need a limit on emanating paths */
+LIST_HEAD(tfile_check_list);
+
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
@@ -276,6 +288,12 @@ ctl_table epoll_table[] = {
};
#endif /* CONFIG_SYSCTL */
+static const struct file_operations eventpoll_fops;
+
+static inline int is_file_epoll(struct file *f)
+{
+ return f->f_op == &eventpoll_fops;
+}
/* Setup the structure that is used as key for the RB tree */
static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = {
.llseek = noop_llseek,
};
-/* Fast test to see if the file is an eventpoll file */
-static inline int is_file_epoll(struct file *f)
-{
- return f->f_op == &eventpoll_fops;
-}
-
/*
* This is called from eventpoll_release() to unlink files from the eventpoll
* interface. We need to have this facility to cleanup correctly files that are
@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
rb_insert_color(&epi->rbn, &ep->rbr);
}
+
+
+#define PATH_ARR_SIZE 5
+/* These are the number paths of length 1 to 5, that we are allowing to emanate
+ * from a single file of interest. For example, we allow 1000 paths of length
+ * 1, to emanate from each file of interest. This essentially represents the
+ * potential wakeup paths, which need to be limited in order to avoid massive
+ * uncontrolled wakeup storms. The common use case should be a single ep which
+ * is connected to n file sources. In this case each file source has 1 path
+ * of length 1. Thus, the numbers below should be more than sufficient.
+ */
+int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };
+int path_count[PATH_ARR_SIZE];
+
+static int path_count_inc(int nests)
+{
+ if (++path_count[nests] > path_limits[nests])
+ return -1;
+ return 0;
+}
+
+static void path_count_init(void)
+{
+ int i;
+
+ for (i = 0; i < PATH_ARR_SIZE; i++)
+ path_count[i] = 0;
+}
+
+static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
+{
+ int error = 0;
+ struct file *file = priv;
+ struct file *child_file;
+ struct epitem *epi;
+
+ list_for_each_entry(epi, &file->f_ep_links, fllink) {
+ child_file = epi->ep->file;
+ if (is_file_epoll(child_file)) {
+ if (list_empty(&child_file->f_ep_links)) {
+ if (path_count_inc(call_nests)) {
+ error = -1;
+ break;
+ }
+ } else {
+ error = ep_call_nested(&poll_loop_ncalls,
+ EP_MAX_NESTS,
+ reverse_path_check_proc,
+ child_file, child_file,
+ current);
+ }
+ if (error != 0)
+ break;
+ } else {
+ printk(KERN_ERR "reverse_path_check_proc: "
+ "file is not an ep!\n");
+ }
+ }
+ return error;
+}
+
+/**
+ * reverse_path_check - The tfile_check_list is list of file *, which have
+ * links that are proposed to be newly added. We need to
+ * make sure that those added links don't add too many
+ * paths such that we will spend all our time waking up
+ * eventpoll objects.
+ *
+ * Returns: Returns zero if the proposed links don't create too many paths,
+ * -1 otherwise.
+ */
+static int reverse_path_check(void)
+{
+ int length = 0;
+ int error = 0;
+ struct file *current_file;
+
+ /* let's call this for all tfiles */
+ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) {
+ length++;
+ path_count_init();
+ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+ reverse_path_check_proc, current_file,
+ current_file, current);
+ if (error)
+ break;
+ }
+ return error;
+}
+
/*
* Must be called with "mtx" held.
*/
@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
*/
ep_rbtree_insert(ep, epi);
+ /* now check if we've created too many backpaths */
+ error = -EINVAL;
+ if (reverse_path_check())
+ goto error_remove_epi;
+
/* We have to drop the new item inside our item list to keep track of it */
spin_lock_irqsave(&ep->lock, flags);
@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
return 0;
+error_remove_epi:
+ spin_lock(&tfile->f_lock);
+ if (ep_is_linked(&epi->fllink))
+ list_del_init(&epi->fllink);
+ spin_unlock(&tfile->f_lock);
+
+ rb_erase(&epi->rbn, &ep->rbr);
+
error_unregister:
ep_unregister_pollwait(ep, epi);
@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
int error = 0;
struct file *file = priv;
struct eventpoll *ep = file->private_data;
+ struct eventpoll *ep_tovisit;
struct rb_node *rbp;
struct epitem *epi;
mutex_lock_nested(&ep->mtx, call_nests + 1);
+ ep->visited = 1;
+ list_add(&ep->visitedllink, &visited_list);
for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
epi = rb_entry(rbp, struct epitem, rbn);
if (unlikely(is_file_epoll(epi->ffd.file))) {
+ ep_tovisit = epi->ffd.file->private_data;
+ if (ep_tovisit->visited)
+ continue;
error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
- ep_loop_check_proc, epi->ffd.file,
- epi->ffd.file->private_data, current);
+ ep_loop_check_proc, epi->ffd.file,
+ ep_tovisit, current);
if (error != 0)
break;
+ } else {
+ /* if we've reached a file that is not associated with
+ * an ep, then then we need to check if the newly added
+ * links are going to add too many wakeup paths. We do
+ * this by adding it to the tfile_check_list, if it's
+ * not already there, and calling reverse_path_check()
+ * during ep_insert()
+ */
+ if (list_empty(&epi->ffd.file->f_tfile_llink))
+ list_add(&epi->ffd.file->f_tfile_llink,
+ &tfile_check_list);
}
}
mutex_unlock(&ep->mtx);
@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
*/
static int ep_loop_check(struct eventpoll *ep, struct file *file)
{
- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+ int ret;
+ struct eventpoll *ep_cur, *ep_next;
+
+ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
ep_loop_check_proc, file, ep, current);
+ /* clear visited list */
+ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) {
+ ep_cur->visited = 0;
+ list_del(&ep_cur->visitedllink);
+ }
+ return ret;
+}
+
+static void clear_tfile_check_list(void)
+{
+ struct file *file;
+
+ /* first clear the tfile_check_list */
+ while (!list_empty(&tfile_check_list)) {
+ file = list_first_entry(&tfile_check_list, struct file,
+ f_tfile_llink);
+ list_del_init(&file->f_tfile_llink);
+ }
+ INIT_LIST_HEAD(&tfile_check_list);
}
/*
@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file)
*/
SYSCALL_DEFINE1(epoll_create1, int, flags)
{
- int error;
+ int error, fd;
struct eventpoll *ep = NULL;
+ struct file *file;
/* Check the EPOLL_* constant for consistency. */
BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
* Creates all the items needed to setup an eventpoll file. That is,
* a file structure and a free file descriptor.
*/
- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
+ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC));
+ if (fd < 0) {
+ error = fd;
+ goto out_free_ep;
+ }
+ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep,
O_RDWR | (flags & O_CLOEXEC));
- if (error < 0)
- ep_free(ep);
-
+ if (IS_ERR(file)) {
+ error = PTR_ERR(file);
+ goto out_free_fd;
+ }
+ fd_install(fd, file);
+ ep->file = file;
+ return fd;
+
+out_free_fd:
+ put_unused_fd(fd);
+out_free_ep:
+ ep_free(ep);
return error;
}
@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
/*
* When we insert an epoll file descriptor, inside another epoll file
* descriptor, there is the change of creating closed loops, which are
- * better be handled here, than in more critical paths.
+ * better be handled here, than in more critical paths. While we are
+ * checking for loops we also determine the list of files reachable
+ * and hang them on the tfile_check_list, so we can check that we
+ * haven't created too many possible wakeup paths.
*
- * We hold epmutex across the loop check and the insert in this case, in
- * order to prevent two separate inserts from racing and each doing the
- * insert "at the same time" such that ep_loop_check passes on both
- * before either one does the insert, thereby creating a cycle.
+ * We need to hold the epmutex across both ep_insert and ep_remove
+ * b/c we want to make sure we are looking at a coherent view of
+ * epoll network.
*/
- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) {
+ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
mutex_lock(&epmutex);
did_lock_epmutex = 1;
- error = -ELOOP;
- if (ep_loop_check(ep, tfile) != 0)
- goto error_tgt_fput;
}
-
+ if (op == EPOLL_CTL_ADD) {
+ if (is_file_epoll(tfile)) {
+ error = -ELOOP;
+ if (ep_loop_check(ep, tfile) != 0)
+ goto error_tgt_fput;
+ } else
+ list_add(&tfile->f_tfile_llink, &tfile_check_list);
+ }
mutex_lock_nested(&ep->mtx, 0);
@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
error = ep_insert(ep, &epds, tfile, fd);
} else
error = -EEXIST;
+ clear_tfile_check_list();
break;
case EPOLL_CTL_DEL:
if (epi)
@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
mutex_unlock(&ep->mtx);
error_tgt_fput:
- if (unlikely(did_lock_epmutex))
+ if (did_lock_epmutex)
mutex_unlock(&epmutex);
fput(tfile);
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index f362733..657ab55 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -61,6 +61,7 @@ struct file;
static inline void eventpoll_init_file(struct file *file)
{
INIT_LIST_HEAD(&file->f_ep_links);
+ INIT_LIST_HEAD(&file->f_tfile_llink);
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ba98668..d393a68 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -985,6 +985,7 @@ struct file {
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_links;
+ struct list_head f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
--
1.7.6.4

View File

@ -1,19 +0,0 @@
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 00beb4f..8fb6844 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -885,8 +885,12 @@ got:
if (IS_DIRSYNC(inode))
ext4_handle_sync(handle);
if (insert_inode_locked(inode) < 0) {
- err = -EINVAL;
- goto fail_drop;
+ /*
+ * Likely a bitmap corruption causing inode to be allocated
+ * twice.
+ */
+ err = -EIO;
+ goto fail;
}
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;

View File

@ -6,7 +6,7 @@ Summary: The Linux kernel
# For a stable, released kernel, released_kernel should be 1. For rawhide
# and/or a kernel built from an rc or git snapshot, released_kernel should
# be 0.
%global released_kernel 1
%global released_kernel 0
# Save original buildid for later if it's defined
%if 0%{?buildid:1}
@ -54,7 +54,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
%global baserelease 8
%global baserelease 1
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@ -66,7 +66,7 @@ Summary: The Linux kernel
%if 0%{?released_kernel}
# Do we have a -stable update to apply?
%define stable_update 1
%define stable_update 0
# Is it a -stable RC?
%define stable_rc 0
# Set rpm version accordingly
@ -85,9 +85,9 @@ Summary: The Linux kernel
# The next upstream release sublevel (base_sublevel+1)
%define upstream_sublevel %(echo $((%{base_sublevel} + 1)))
# The rc snapshot level
%define rcrev 7
%define rcrev 1
# The git snapshot level
%define gitrev 5
%define gitrev 0
# Set rpm version accordingly
%define rpmversion 3.%{upstream_sublevel}.0
%endif
@ -218,7 +218,7 @@ Summary: The Linux kernel
#
# (Uncomment the '#' and both spaces below to disable with_backports.)
#
# % define with_backports 0
%define with_backports 0
#######################################################################
%define make_target bzImage
@ -719,8 +719,7 @@ Patch1101: linux-3.1-keys-remove-special-keyring.patch
# patches headed upstream
Patch12016: disable-i8042-check-on-apple-mac.patch
Patch12026: block-stray-block-put-after-teardown.patch
Patch12030: epoll-limit-paths.patch
#atch12026: block-stray-block-put-after-teardown.patch
Patch12303: dmar-disable-when-ricoh-multifunction.patch
@ -733,53 +732,20 @@ Patch20000: utrace.patch
Patch21000: arm-omap-dt-compat.patch
Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch
#rhbz 753236
Patch21029: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch
#rhbz 590880
Patch21030: alps.patch
#rhbz 717735
Patch21045: nfs-client-freezer.patch
#rhbz 770233
Patch21065: Bluetooth-Add-support-for-BCM20702A0-0a5c-21e3.patch
Patch21070: ext4-Support-check-none-nocheck-mount-options.patch
Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch
#rhbz 769766
Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
#rhbz 773392
Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch
#rhbz 728740
Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch
Patch21080: sysfs-msi-irq-per-device.patch
#rhbz 782686
Patch21082: procfs-parse-mount-options.patch
Patch21083: procfs-add-hidepid-and-gid-mount-options.patch
Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch
#rhbz 782681
Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch
#rhbz 782696
Patch21086: Unused-iocbs-in-a-batch-should-not-be-accounted-as-a.patch
Patch21090: bcma-brcmsmac-compat.patch
Patch21091: pci-Rework-ASPM-disable-code.patch
Patch21091: kmemleak.patch
# compat-wireless patches
Patch50000: compat-wireless-config-fixups.patch
Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch
Patch50002: compat-wireless-integrated-build.patch
Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch
Patch50100: brcmfmac-gcc47.patch
@ -1341,7 +1307,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch
#
# ARM
#
ApplyPatch arm-omap-dt-compat.patch
#pplyPatch arm-omap-dt-compat.patch
ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch
#
@ -1448,8 +1414,7 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch
# Patches headed upstream
ApplyPatch disable-i8042-check-on-apple-mac.patch
ApplyPatch epoll-limit-paths.patch
ApplyPatch block-stray-block-put-after-teardown.patch
#pplyPatch block-stray-block-put-after-teardown.patch
# rhbz#605888
ApplyPatch dmar-disable-when-ricoh-multifunction.patch
@ -1458,54 +1423,20 @@ ApplyPatch revert-efi-rtclock.patch
ApplyPatch efi-dont-map-boot-services-on-32bit.patch
# utrace.
ApplyPatch utrace.patch
# Add msi irq ennumeration in sysfs for devices
ApplyPatch sysfs-msi-irq-per-device.patch
# pplyPatch utrace.patch
%if !%{with_backports}
# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331
ApplyPatch bcma-brcmsmac-compat.patch
%endif
ApplyPatch pci-Rework-ASPM-disable-code.patch
#rhbz 753236
ApplyPatch nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch
#rhbz 590880
ApplyPatch alps.patch
#rhbz 717735
ApplyPatch nfs-client-freezer.patch
#rhbz 770233
ApplyPatch Bluetooth-Add-support-for-BCM20702A0-0a5c-21e3.patch
ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch
ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch
ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
#rhbz 773392
ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch
#rhbz 728740
ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch
#rhbz 782686
ApplyPatch procfs-parse-mount-options.patch
ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch
ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch
#rhbz 782681
ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch
#rhbz 782696
ApplyPatch Unused-iocbs-in-a-batch-should-not-be-accounted-as-a.patch
ApplyPatch kmemleak.patch
# END OF PATCH APPLICATIONS
%endif
@ -1571,8 +1502,6 @@ cd compat-wireless-%{cwversion}
ApplyPatch compat-wireless-config-fixups.patch
ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch
ApplyPatch compat-wireless-integrated-build.patch
ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch
ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
ApplyPatch brcmfmac-gcc47.patch
@ -2345,6 +2274,9 @@ fi
# ||----w |
# || ||
%changelog
* Fri Jan 20 2012 Josh Boyer <jwboyer@redhat.com>
- Rebase to Linux 3.3-rc1
* Thu Jan 19 2012 John W. Linville <linville@redhat.com>
- Pass the same make options to compat-wireless as to the base kernel

100
kmemleak.patch Normal file
View File

@ -0,0 +1,100 @@
Delivered-To: jwboyer@gmail.com
Received: by 10.216.166.66 with SMTP id f44cs7120wel;
Fri, 20 Jan 2012 03:02:14 -0800 (PST)
Received: by 10.68.72.8 with SMTP id z8mr60494730pbu.111.1327057318390;
Fri, 20 Jan 2012 03:01:58 -0800 (PST)
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
by mx.google.com with ESMTP id q8si4181579pbn.101.2012.01.20.03.01.56;
Fri, 20 Jan 2012 03:01:58 -0800 (PST)
Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S1751460Ab2ATLBU (ORCPT <rfc822;ramashish.lists@gmail.com>
+ 99 others); Fri, 20 Jan 2012 06:01:20 -0500
Received: from cam-admin0.cambridge.arm.com ([217.140.96.50]:34737 "EHLO
cam-admin0.cambridge.arm.com" rhost-flags-OK-OK-OK-OK)
by vger.kernel.org with ESMTP id S1750877Ab2ATLBT (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Fri, 20 Jan 2012 06:01:19 -0500
Received: from arm.com (e102109-lin.cambridge.arm.com [10.1.69.68])
by cam-admin0.cambridge.arm.com (8.12.6/8.12.6) with ESMTP id q0KB1CWq000059;
Fri, 20 Jan 2012 11:01:12 GMT
Date: Fri, 20 Jan 2012 11:01:11 +0000
From: Catalin Marinas <catalin.marinas@arm.com>
To: Dirk Gouders <gouders@et.bocholt.fh-gelsenkirchen.de>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [Problem] kernel hangs at boot (bisected 892d208bcf)
Message-ID: <20120120110111.GB30612@arm.com>
References: <gi39bcyff8.fsf@mx10.gouders.net>
<20120119110121.GC9268@arm.com>
<gi1uqvsx8n.fsf@karga.hank.lab>
<20120119140058.GA19036@arm.com>
<gik44nrc52.fsf@karga.hank.lab>
<20120119153732.GB20558@arm.com>
<gi1uqvwpt2.fsf@mx10.gouders.net>
<gimx9jv50u.fsf@mx10.gouders.net>
<giipk7v2hv.fsf@mx10.gouders.net>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <giipk7v2hv.fsf@mx10.gouders.net>
Thread-Topic: [Problem] kernel hangs at boot (bisected 892d208bcf)
Accept-Language: en-GB, en-US
Content-Language: en-US
User-Agent: Mutt/1.5.20 (2009-06-14)
Sender: linux-kernel-owner@vger.kernel.org
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
On Thu, Jan 19, 2012 at 08:52:44PM +0000, Dirk Gouders wrote:
> Dirk Gouders <gouders@et.bocholt.fh-gelsenkirchen.de> writes:
> I want to note that in my config CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF is
> set which causes kmemleak_disable() to be called in kmemleak_init().
Thanks for the investigation. Could you please try the patch below?
Thanks.
From 09e7bd41ff3fd07e4c5eea7bbb0a045921eb5944 Mon Sep 17 00:00:00 2001
From: Catalin Marinas <catalin.marinas@arm.com>
Date: Fri, 20 Jan 2012 10:42:40 +0000
Subject: [PATCH] kmemleak: Disable early logging when kmemleak is off by
default
Commit b6693005 (kmemleak: When the early log buffer is exceeded, report
the actual number) deferred the disabling of the early logging to
kmemleak_init(). However, when CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y, the
early logging was no longer disabled causing __init kmemleak functions
to be called even after the kernel freed the init memory. This patch
disables the early logging during kmemleak_init() if kmemleak is left
disabled.
Reported-by: Dirk Gouders <gouders@et.bocholt.fh-gelsenkirchen.de>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
mm/kmemleak.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index f9f7310..45eb621 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1757,6 +1757,7 @@ void __init kmemleak_init(void)
#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
if (!kmemleak_skip_disable) {
+ atomic_set(&kmemleak_early_log, 0);
kmemleak_disable();
return;
}
--
Catalin
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -1,13 +1,13 @@
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index d8d7596..a1b7117 100644
index eaef02a..2029819 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -71,7 +71,7 @@ MODULE_AUTHOR("Bruno Ducrot");
@@ -69,7 +69,7 @@ MODULE_AUTHOR("Bruno Ducrot");
MODULE_DESCRIPTION("ACPI Video Driver");
MODULE_LICENSE("GPL");
-static int brightness_switch_enabled = 1;
+static int brightness_switch_enabled = 0;
-static bool brightness_switch_enabled = 1;
+static bool brightness_switch_enabled = 0;
module_param(brightness_switch_enabled, bool, 0644);
static int acpi_video_bus_add(struct acpi_device *device);
/*

View File

@ -1,47 +0,0 @@
Since:
commit 816c04fe7ef01dd9649f5ccfe796474db8708be5
Author: Christian Lamparter <chunkeey@googlemail.com>
Date: Sat Apr 30 15:24:30 2011 +0200
mac80211: consolidate MIC failure report handling
is possible to that we dereference rx->key == NULL when driver set
RX_FLAG_MMIC_STRIPPED and not RX_FLAG_IV_STRIPPED and we are in
promiscuous mode. This happen with rt73usb and rt61pci at least.
Before the commit we always check rx->key against NULL, so I assume
fix should be done in mac80211 (also mic_fail path has similar check).
References:
https://bugzilla.redhat.com/show_bug.cgi?id=769766
http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/2012-January/004395.html
Cc: stable@vger.kernel.org # 3.0+
Reported-by: Stuart D Gathman <stuart@gathman.org>
Reported-by: Kai Wohlfahrt <kai.scorpio@gmail.com>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
net/mac80211/wpa.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 93aab07..422b798 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -106,7 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_MMIC_ERROR)
goto mic_fail;
- if (!(status->flag & RX_FLAG_IV_STRIPPED))
+ if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
goto update_iv;
return RX_CONTINUE;
--
1.7.1
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

View File

@ -1,197 +0,0 @@
@@ -, +, @@
fs/nfs/inode.c | 3 ++-
fs/nfs/nfs3proc.c | 3 ++-
fs/nfs/nfs4proc.c | 5 +++--
fs/nfs/proc.c | 3 ++-
include/linux/freezer.h | 28 ++++++++++++++++++++++++++++
net/sunrpc/sched.c | 3 ++-
6 files changed, 39 insertions(+), 6 deletions(-)
--- a/fs/nfs/inode.c
+++ a/fs/nfs/inode.c
@@ -38,6 +38,7 @@
#include <linux/nfs_xdr.h>
#include <linux/slab.h>
#include <linux/compat.h>
+#include <linux/freezer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
- schedule();
+ freezable_schedule();
return 0;
}
--- a/fs/nfs/nfs3proc.c
+++ a/fs/nfs/nfs3proc.c
@@ -17,6 +17,7 @@
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include <linux/nfs_mount.h>
+#include <linux/freezer.h>
#include "iostat.h"
#include "internal.h"
@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
res = rpc_call_sync(clnt, msg, flags);
if (res != -EJUKEBOX && res != -EKEYEXPIRED)
break;
- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
res = -ERESTARTSYS;
} while (!fatal_signal_pending(current));
return res;
--- a/fs/nfs/nfs4proc.c
+++ a/fs/nfs/nfs4proc.c
@@ -53,6 +53,7 @@
#include <linux/sunrpc/bc_xprt.h>
#include <linux/xattr.h>
#include <linux/utsname.h>
+#include <linux/freezer.h>
#include "nfs4_fs.h"
#include "delegation.h"
@@ -241,7 +242,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
*timeout = NFS4_POLL_RETRY_MIN;
if (*timeout > NFS4_POLL_RETRY_MAX)
*timeout = NFS4_POLL_RETRY_MAX;
- schedule_timeout_killable(*timeout);
+ freezable_schedule_timeout_killable(*timeout);
if (fatal_signal_pending(current))
res = -ERESTARTSYS;
*timeout <<= 1;
@@ -3950,7 +3951,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4
static unsigned long
nfs4_set_lock_task_retry(unsigned long timeout)
{
- schedule_timeout_killable(timeout);
+ freezable_schedule_timeout_killable(timeout);
timeout <<= 1;
if (timeout > NFS4_LOCK_MAXTIMEOUT)
return NFS4_LOCK_MAXTIMEOUT;
--- a/fs/nfs/proc.c
+++ a/fs/nfs/proc.c
@@ -41,6 +41,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
+#include <linux/freezer.h>
#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
res = rpc_call_sync(clnt, msg, flags);
if (res != -EKEYEXPIRED)
break;
- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
res = -ERESTARTSYS;
} while (!fatal_signal_pending(current));
return res;
--- a/include/linux/freezer.h
+++ a/include/linux/freezer.h
@@ -135,6 +135,29 @@ static inline void set_freezable_with_signal(void)
}
/*
+ * These macros are intended to be used whenever you want allow a task that's
+ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note
+ * that neither return any clear indication of whether a freeze event happened
+ * while in this function.
+ */
+
+/* Like schedule(), but should not block the freezer. */
+#define freezable_schedule() \
+({ \
+ freezer_do_not_count(); \
+ schedule(); \
+ freezer_count(); \
+})
+
+/* Like schedule_timeout_killable(), but should not block the freezer. */
+#define freezable_schedule_timeout_killable(timeout) \
+({ \
+ freezer_do_not_count(); \
+ schedule_timeout_killable(timeout); \
+ freezer_count(); \
+})
+
+/*
* Freezer-friendly wrappers around wait_event_interruptible(),
* wait_event_killable() and wait_event_interruptible_timeout(), originally
* defined in <linux/wait.h>
@@ -194,6 +217,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {}
static inline void set_freezable_with_signal(void) {}
+#define freezable_schedule() schedule()
+
+#define freezable_schedule_timeout_killable(timeout) \
+ schedule_timeout_killable(timeout)
+
#define wait_event_freezable(wq, condition) \
wait_event_interruptible(wq, condition)
--- a/net/sunrpc/sched.c
+++ a/net/sunrpc/sched.c
@@ -18,6 +18,7 @@
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <linux/sunrpc/clnt.h>
@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
- schedule();
+ freezable_schedule();
return 0;
}
include/linux/freezer.h | 21 ++++++++++++++++++---
1 files changed, 18 insertions(+), 3 deletions(-)
--- a/include/linux/freezer.h
+++ a/include/linux/freezer.h
@@ -141,18 +141,33 @@ static inline void set_freezable_with_signal(void)
* while in this function.
*/
-/* Like schedule(), but should not block the freezer. */
+/*
+ * Like schedule(), but should not block the freezer. It may return immediately
+ * if it ends up racing with the freezer. Callers must be able to deal with
+ * spurious wakeups.
+ */
#define freezable_schedule() \
({ \
freezer_do_not_count(); \
- schedule(); \
+ if (!try_to_freeze()) \
+ schedule(); \
freezer_count(); \
})
-/* Like schedule_timeout_killable(), but should not block the freezer. */
+/*
+ * Like schedule_timeout_killable(), but should not block the freezer. It may
+ * end up returning immediately if it ends up racing with the freezer. Callers
+ * must be able to deal with the loose wakeup timing that can occur when the
+ * freezer races in. When that occurs, this function will return the timeout
+ * value instead of 0.
+ */
#define freezable_schedule_timeout_killable(timeout) \
({ \
freezer_do_not_count(); \
+ if (try_to_freeze()) { \
+ freezer_count(); \
+ return timeout; \
+ } \
schedule_timeout_killable(timeout); \
freezer_count(); \
})

View File

@ -1,118 +0,0 @@
From: Andy Adamson <andros@xxxxxxxxxx>
The NFSv4 bitmap size is unbounded: a server can return an arbitrary
sized bitmap in an FATTR4_WORD0_ACL request. Replace using the
nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server
with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data
xdr length to the (cached) acl page data.
This is a general solution to commit e5012d1f "NFSv4.1: update
nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead
when getting ACLs.
Cc:stable@xxxxxxxxxx
Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
---
fs/nfs/nfs4proc.c | 20 ++++++++++++++++++--
fs/nfs/nfs4xdr.c | 15 ++++++++++++---
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index deb88d9..97014dd 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3671,6 +3671,22 @@ static void nfs4_zap_acl_attr(struct inode *inode)
nfs4_set_cached_acl(inode, NULL);
}
+/*
+ * The bitmap xdr length, bitmasks, and the attr xdr length are stored in
+ * the acl cache to handle variable length bitmasks. Just copy the acl data.
+ */
+static void nfs4_copy_acl(char *buf, char *acl_data, size_t acl_len)
+{
+ __be32 *q, *p = (__be32 *)acl_data;
+ int32_t len;
+
+ len = be32_to_cpup(p); /* number of bitmasks */
+ len += 2; /* add words for bitmap and attr xdr len */
+ q = p + len;
+ len = len << 2; /* convert to bytes for acl_len math */
+ memcpy(buf, (char *)q, acl_len - len);
+}
+
static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
{
struct nfs_inode *nfsi = NFS_I(inode);
@@ -3688,7 +3704,7 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_
ret = -ERANGE; /* see getxattr(2) man page */
if (acl->len > buflen)
goto out;
- memcpy(buf, acl->data, acl->len);
+ nfs4_copy_acl(buf, acl->data, acl->len);
out_len:
ret = acl->len;
out:
@@ -3763,7 +3779,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
if (res.acl_len > buflen)
goto out_free;
if (localpage)
- memcpy(buf, resp_buf, res.acl_len);
+ nfs4_copy_acl(buf, resp_buf, res.acl_len);
}
ret = res.acl_len;
out_free:
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index f9fd96d..9c07380 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2513,7 +2513,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
encode_compound_hdr(xdr, req, &hdr);
encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fh, &hdr);
- replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
+ replen = hdr.replen + op_decode_hdr_maxsz + 1;
encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr);
xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
@@ -4955,7 +4955,7 @@ decode_restorefh(struct xdr_stream *xdr)
static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
size_t *acl_len)
{
- __be32 *savep;
+ __be32 *savep, *bm_p;
uint32_t attrlen,
bitmap[3] = {0};
struct kvec *iov = req->rq_rcv_buf.head;
@@ -4964,6 +4964,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
*acl_len = 0;
if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
goto out;
+ bm_p = xdr->p;
if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
goto out;
if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
@@ -4972,12 +4973,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
- size_t hdrlen;
+ size_t hdrlen, len;
u32 recvd;
+ /*The bitmap (xdr len + bitmasks) and the attr xdr len words
+ * are stored with the acl data to handle the problem of
+ * variable length bitmasks.*/
+ xdr->p = bm_p;
+ len = be32_to_cpup(bm_p);
+ len += 2; /* add bitmap and attr xdr len words */
+
/* We ignore &savep and don't do consistency checks on
* the attr length. Let userspace figure it out.... */
hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
+ attrlen += len << 2; /* attrlen is in bytes */
recvd = req->rq_rcv_buf.len - hdrlen;
if (attrlen > recvd) {
dprintk("NFS: server cheating in getattr"
--
1.7.6.4

View File

@ -1,287 +0,0 @@
Path: news.gmane.org!not-for-mail
From: Matthew Garrett <mjg@redhat.com>
Newsgroups: gmane.linux.acpi.devel,gmane.linux.kernel.pci,gmane.linux.kernel
Subject: [PATCH] pci: Rework ASPM disable code
Date: Thu, 10 Nov 2011 16:38:33 -0500
Lines: 232
Approved: news@gmane.org
Message-ID: <1320961113-5050-1-git-send-email-mjg@redhat.com>
NNTP-Posting-Host: lo.gmane.org
X-Trace: dough.gmane.org 1320961145 13112 80.91.229.12 (10 Nov 2011 21:39:05 GMT)
X-Complaints-To: usenet@dough.gmane.org
NNTP-Posting-Date: Thu, 10 Nov 2011 21:39:05 +0000 (UTC)
Cc: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org,
linux-kernel@vger.kernel.org, Matthew Garrett <mjg@redhat.com>
To: jbarnes@virtuousgeek.org
Original-X-From: linux-acpi-owner@vger.kernel.org Thu Nov 10 22:38:57 2011
Return-path: <linux-acpi-owner@vger.kernel.org>
Envelope-to: glad-acpi-devel@lo.gmane.org
Original-Received: from vger.kernel.org ([209.132.180.67])
by lo.gmane.org with esmtp (Exim 4.69)
(envelope-from <linux-acpi-owner@vger.kernel.org>)
id 1ROcKm-0003jN-CL
for glad-acpi-devel@lo.gmane.org; Thu, 10 Nov 2011 22:38:56 +0100
Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S1751342Ab1KJViu (ORCPT <rfc822;glad-acpi-devel@m.gmane.org>);
Thu, 10 Nov 2011 16:38:50 -0500
Original-Received: from mx1.redhat.com ([209.132.183.28]:32030 "EHLO mx1.redhat.com"
rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP
id S1750805Ab1KJVit (ORCPT <rfc822;linux-acpi@vger.kernel.org>);
Thu, 10 Nov 2011 16:38:49 -0500
Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22])
by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAALcmdw013333
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK);
Thu, 10 Nov 2011 16:38:49 -0500
Original-Received: from cavan.codon.org.uk (ovpn-113-157.phx2.redhat.com [10.3.113.157])
by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAALclkW022022
(version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO);
Thu, 10 Nov 2011 16:38:48 -0500
Original-Received: from 209-6-41-104.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.41.104] helo=localhost.localdomain)
by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)
(Exim 4.72)
(envelope-from <mjg@redhat.com>)
id 1ROcKa-0000F4-E4; Thu, 10 Nov 2011 21:38:44 +0000
X-SA-Do-Not-Run: Yes
X-SA-Exim-Connect-IP: 209.6.41.104
X-SA-Exim-Mail-From: mjg@redhat.com
X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false
X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22
Original-Sender: linux-acpi-owner@vger.kernel.org
Precedence: bulk
List-ID: <linux-acpi.vger.kernel.org>
X-Mailing-List: linux-acpi@vger.kernel.org
Xref: news.gmane.org gmane.linux.acpi.devel:51182 gmane.linux.kernel.pci:12503 gmane.linux.kernel:1214427
Archived-At: <http://permalink.gmane.org/gmane.linux.acpi.devel/51182>
Right now we forcibly clear ASPM state on all devices if the BIOS indicates
that the feature isn't supported. Based on the Microsoft presentation
"PCI Express In Depth for Windows Vista and Beyond", I'm starting to think
that this may be an error. The implication is that unless the platform
grants full control via _OSC, Windows will not touch any PCIe features -
including ASPM. In that case clearing ASPM state would be an error unless
the platform has granted us that control.
This patch reworks the ASPM disabling code such that the actual clearing
of state is triggered by a successful handoff of PCIe control to the OS.
The general ASPM code undergoes some changes in order to ensure that the
ability to clear the bits isn't overridden by ASPM having already been
disabled. Further, this theoretically now allows for situations where
only a subset of PCIe roots hand over control, leaving the others in the
BIOS state.
It's difficult to know for sure that this is the right thing to do -
there's zero public documentation on the interaction between all of these
components. But enough vendors enable ASPM on platforms and then set this
bit that it seems likely that they're expecting the OS to leave them alone.
Measured to save around 5W on an idle Thinkpad X220.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/acpi/pci_root.c | 7 +++++
drivers/pci/pci-acpi.c | 1 -
drivers/pci/pcie/aspm.c | 58 +++++++++++++++++++++++++++++----------------
include/linux/pci-aspm.h | 4 +-
4 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 2672c79..7aff631 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (ACPI_SUCCESS(status)) {
dev_info(root->bus->bridge,
"ACPI _OSC control (0x%02x) granted\n", flags);
+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+ /*
+ * We have ASPM control, but the FADT indicates
+ * that it's unsupported. Clear it.
+ */
+ pcie_clear_aspm(root->bus);
+ }
} else {
dev_info(root->bus->bridge,
"ACPI _OSC request failed (%s), "
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 4ecb640..c8e7585 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -395,7 +395,6 @@ static int __init acpi_pci_init(void)
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
- pcie_clear_aspm();
pcie_no_aspm();
}
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index cbfbab1..1cfbf22 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -68,7 +68,7 @@ struct pcie_link_state {
struct aspm_latency acceptable[8];
};
-static int aspm_disabled, aspm_force, aspm_clear_state;
+static int aspm_disabled, aspm_force;
static bool aspm_support_enabled = true;
static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list);
@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
int pos;
u32 reg32;
- if (aspm_clear_state)
- return -EINVAL;
-
/*
* Some functions in a slot might not all be PCIe functions,
* very strange. Disable ASPM for the whole slot
@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
return;
- if (aspm_disabled && !aspm_clear_state)
- return;
-
/* VIA has a strange chipset, root port is under a bridge */
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
pdev->bus->self)
@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
* the BIOS's expectation, we'll do so once pci_enable_device() is
* called.
*/
- if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) {
+ if (aspm_policy != POLICY_POWERSAVE) {
pcie_config_aspm_path(link);
pcie_set_clkpm(link, policy_to_clkpm_state(link));
}
@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;
- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) ||
- !parent || !parent->link_state)
+ if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
return;
if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
* pci_disable_link_state - disable pci device's link state, so the link will
* never enter specific states
*/
-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
+ bool force)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;
- if (aspm_disabled || !pci_is_pcie(pdev))
+ if (aspm_disabled && !force)
+ return;
+
+ if (!pci_is_pcie(pdev))
return;
+
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
parent = pdev;
@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, false);
+ __pci_disable_link_state(pdev, state, false, false);
}
EXPORT_SYMBOL(pci_disable_link_state_locked);
void pci_disable_link_state(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, true);
+ __pci_disable_link_state(pdev, state, true, false);
}
EXPORT_SYMBOL(pci_disable_link_state);
+void pcie_clear_aspm(struct pci_bus *bus)
+{
+ struct pci_dev *child;
+
+ /*
+ * Clear any ASPM setup that the firmware has carried out on this bus
+ */
+ list_for_each_entry(child, &bus->devices, bus_list) {
+ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
+ PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM,
+ false, true);
+ }
+}
+
static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
{
int i;
@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
static int __init pcie_aspm_disable(char *str)
{
if (!strcmp(str, "off")) {
+ aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
aspm_support_enabled = false;
printk(KERN_INFO "PCIe ASPM is disabled\n");
@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str)
__setup("pcie_aspm=", pcie_aspm_disable);
-void pcie_clear_aspm(void)
-{
- if (!aspm_force)
- aspm_clear_state = 1;
-}
-
void pcie_no_aspm(void)
{
- if (!aspm_force)
+ /*
+ * Disabling ASPM is intended to prevent the kernel from modifying
+ * existing hardware state, not to clear existing state. To that end:
+ * (a) set policy to POLICY_DEFAULT in order to avoid changing state
+ * (b) prevent userspace from changing policy
+ */
+ if (!aspm_force) {
+ aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
+ }
}
/**
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
index 7cea7b6..c832014 100644
--- a/include/linux/pci-aspm.h
+++ b/include/linux/pci-aspm.h
@@ -29,7 +29,7 @@ extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
extern void pci_disable_link_state(struct pci_dev *pdev, int state);
extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-extern void pcie_clear_aspm(void);
+extern void pcie_clear_aspm(struct pci_bus *bus);
extern void pcie_no_aspm(void);
#else
static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
@@ -47,7 +47,7 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
{
}
-static inline void pcie_clear_aspm(void)
+static inline void pcie_clear_aspm(struct pci_bus *bus)
{
}
static inline void pcie_no_aspm(void)
--
1.7.7.1
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

View File

@ -1,268 +0,0 @@
From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Tue, 17 Jan 2012 15:21:19 -0800
Subject: [PATCH] proc: clean up and fix /proc/<pid>/mem handling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Jüri Aedla reported that the /proc/<pid>/mem handling really isn't very
robust, and it also doesn't match the permission checking of any of the
other related files.
This changes it to do the permission checks at open time, and instead of
tracking the process, it tracks the VM at the time of the open. That
simplifies the code a lot, but does mean that if you hold the file
descriptor open over an execve(), you'll continue to read from the _old_
VM.
That is different from our previous behavior, but much simpler. If
somebody actually finds a load where this matters, we'll need to revert
this commit.
I suspect that nobody will ever notice - because the process mapping
addresses will also have changed as part of the execve. So you cannot
actually usefully access the fd across a VM change simply because all
the offsets for IO would have changed too.
Reported-by: Jüri Aedla <asd@ut.ee>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
fs/proc/base.c | 145 +++++++++++++++-----------------------------------------
1 files changed, 39 insertions(+), 106 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 5485a53..662ddf2 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
return result;
}
-static struct mm_struct *__check_mem_permission(struct task_struct *task)
-{
- struct mm_struct *mm;
-
- mm = get_task_mm(task);
- if (!mm)
- return ERR_PTR(-EINVAL);
-
- /*
- * A task can always look at itself, in case it chooses
- * to use system calls instead of load instructions.
- */
- if (task == current)
- return mm;
-
- /*
- * If current is actively ptrace'ing, and would also be
- * permitted to freshly attach with ptrace now, permit it.
- */
- if (task_is_stopped_or_traced(task)) {
- int match;
- rcu_read_lock();
- match = (ptrace_parent(task) == current);
- rcu_read_unlock();
- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
- return mm;
- }
-
- /*
- * No one else is allowed.
- */
- mmput(mm);
- return ERR_PTR(-EPERM);
-}
-
-/*
- * If current may access user memory in @task return a reference to the
- * corresponding mm, otherwise ERR_PTR.
- */
-static struct mm_struct *check_mem_permission(struct task_struct *task)
-{
- struct mm_struct *mm;
- int err;
-
- /*
- * Avoid racing if task exec's as we might get a new mm but validate
- * against old credentials.
- */
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
- if (err)
- return ERR_PTR(err);
-
- mm = __check_mem_permission(task);
- mutex_unlock(&task->signal->cred_guard_mutex);
-
- return mm;
-}
-
-struct mm_struct *mm_for_maps(struct task_struct *task)
+static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
{
struct mm_struct *mm;
int err;
@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
mm = get_task_mm(task);
if (mm && mm != current->mm &&
- !ptrace_may_access(task, PTRACE_MODE_READ)) {
+ !ptrace_may_access(task, mode)) {
mmput(mm);
mm = ERR_PTR(-EACCES);
}
@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
return mm;
}
+struct mm_struct *mm_for_maps(struct task_struct *task)
+{
+ return mm_access(task, PTRACE_MODE_READ);
+}
+
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
int res = 0;
@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = {
static int mem_open(struct inode* inode, struct file* file)
{
- file->private_data = (void*)((long)current->self_exec_id);
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ struct mm_struct *mm;
+
+ if (!task)
+ return -ESRCH;
+
+ mm = mm_access(task, PTRACE_MODE_ATTACH);
+ put_task_struct(task);
+
+ if (IS_ERR(mm))
+ return PTR_ERR(mm);
+
/* OK to pass negative loff_t, we can catch out-of-range */
file->f_mode |= FMODE_UNSIGNED_OFFSET;
+ file->private_data = mm;
+
return 0;
}
static ssize_t mem_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ int ret;
char *page;
unsigned long src = *ppos;
- int ret = -ESRCH;
- struct mm_struct *mm;
+ struct mm_struct *mm = file->private_data;
- if (!task)
- goto out_no_task;
+ if (!mm)
+ return 0;
- ret = -ENOMEM;
page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
- goto out;
-
- mm = check_mem_permission(task);
- ret = PTR_ERR(mm);
- if (IS_ERR(mm))
- goto out_free;
-
- ret = -EIO;
-
- if (file->private_data != (void*)((long)current->self_exec_id))
- goto out_put;
+ return -ENOMEM;
ret = 0;
@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
}
*ppos = src;
-out_put:
- mmput(mm);
-out_free:
free_page((unsigned long) page);
-out:
- put_task_struct(task);
-out_no_task:
return ret;
}
@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
{
int copied;
char *page;
- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
unsigned long dst = *ppos;
- struct mm_struct *mm;
+ struct mm_struct *mm = file->private_data;
- copied = -ESRCH;
- if (!task)
- goto out_no_task;
+ if (!mm)
+ return 0;
- copied = -ENOMEM;
page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
- goto out_task;
-
- mm = check_mem_permission(task);
- copied = PTR_ERR(mm);
- if (IS_ERR(mm))
- goto out_free;
-
- copied = -EIO;
- if (file->private_data != (void *)((long)current->self_exec_id))
- goto out_mm;
+ return -ENOMEM;
copied = 0;
while (count > 0) {
@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
}
*ppos = dst;
-out_mm:
- mmput(mm);
-out_free:
free_page((unsigned long) page);
-out_task:
- put_task_struct(task);
-out_no_task:
return copied;
}
@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
return file->f_pos;
}
+static int mem_release(struct inode *inode, struct file *file)
+{
+ struct mm_struct *mm = file->private_data;
+
+ mmput(mm);
+ return 0;
+}
+
static const struct file_operations proc_mem_operations = {
.llseek = mem_lseek,
.read = mem_read,
.write = mem_write,
.open = mem_open,
+ .release = mem_release,
};
static ssize_t environ_read(struct file *file, char __user *buf,
--
1.7.7.5

View File

@ -1,44 +0,0 @@
From a2ef990ab5a6705a356d146dd773a3b359787497 Mon Sep 17 00:00:00 2001
From: Xiaotian Feng <xtfeng@gmail.com>
Date: Thu, 12 Jan 2012 17:17:08 -0800
Subject: [PATCH] proc: fix null pointer deref in proc_pid_permission()
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: [<ffffffff81217d34>] 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 <dannyfeng@tencent.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Vasiliy Kulikov <segoon@openwall.com>
Cc: Stephen Wilson <wilsons@start.ca>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
fs/proc/base.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
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);
--
1.7.7.5

View File

@ -1,342 +0,0 @@
From 0499680a42141d86417a8fbaa8c8db806bea1201 Mon Sep 17 00:00:00 2001
From: Vasiliy Kulikov <segooon@gmail.com>
Date: Tue, 10 Jan 2012 15:11:31 -0800
Subject: [PATCH] procfs: add hidepid= and gid= mount options
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/<pid>/ 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 <segoon@openwall.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Greg KH <greg@kroah.com>
Cc: Theodore Tso <tytso@MIT.EDU>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: James Morris <jmorris@namei.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
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(-)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 0ec91f0..12fee13 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -41,6 +41,8 @@ Table of Contents
3.5 /proc/<pid>/mountinfo - Information about mounts
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
+ 4 Configuring procfs
+ 4.1 Mount options
------------------------------------------------------------------------------
Preface
@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value
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/<pid>/ access mode.
+ gid= Set the group authorized to learn processes information.
+
+hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
+(default).
+
+hidepid=1 means users may not access any /proc/<pid>/ 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/<pid>/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/<pid>/ 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/<pid>/ 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.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4d755fe..8173dfd 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -631,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
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,
};
@@ -1615,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
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);
@@ -1623,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
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);
@@ -3119,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
.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)
@@ -3322,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
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)
{
@@ -3329,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
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;
@@ -3350,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
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;
}
@@ -3686,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = {
.lookup = proc_task_lookup,
.getattr = proc_task_getattr,
.setattr = proc_setattr,
+ .permission = proc_pid_permission,
};
static const struct file_operations proc_task_operations = {
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 27c762f..84fd323 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -106,6 +106,14 @@ void __init proc_init_inodecache(void)
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;
}
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 6a8ac1d..46a15d8 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data)
}
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 @@ 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);
+ int option;
if (!options)
return 1;
@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid)
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);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 38d1032..e7cf666 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -30,6 +30,8 @@ struct pid_namespace {
#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;
--
1.7.7.5

View File

@ -1,173 +0,0 @@
From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001
From: Vasiliy Kulikov <segooon@gmail.com>
Date: Tue, 10 Jan 2012 15:11:27 -0800
Subject: [PATCH] procfs: parse mount options
Add support for procfs mount options. Actual mount options are coming in
the next patches.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Greg KH <greg@kroah.com>
Cc: Theodore Tso <tytso@MIT.EDU>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: James Morris <jmorris@namei.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
fs/proc/inode.c | 10 +++++++++
fs/proc/internal.h | 1 +
fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 51a1766..27c762f 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -7,6 +7,7 @@
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
+#include <linux/pid_namespace.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
@@ -17,7 +18,9 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysctl.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/mount.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void)
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)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 7838e5c..2925775 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde);
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
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 03102d9..6a8ac1d 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -18,6 +18,7 @@
#include <linux/bitops.h>
#include <linux/mount.h>
#include <linux/pid_namespace.h>
+#include <linux/parser.h>
#include "internal.h"
@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data)
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 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
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 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
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);
--
1.7.7.5

View File

@ -1,8 +1,16 @@
commit d80d983c0fbfe0b0f6bd83c4279e1077c31e7fe4
Author: Josh Boyer <jwboyer@redhat.com>
Date: Fri Jan 20 10:12:15 2012 -0500
Revert "x86: Serialize EFI time accesses on rtc_lock"
This reverts commit ef68c8f87ed13f65df867dddf36c0e185b27b942.
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 3ae4128..e17c6d2 100644
index 4cf9bd0..457e37a 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -89,50 +89,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
@@ -90,50 +90,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{
@ -59,7 +67,7 @@ index 3ae4128..e17c6d2 100644
}
static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -232,14 +208,11 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
@@ -233,15 +209,12 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
efi_time_cap_t *tc)
{
@ -68,7 +76,8 @@ index 3ae4128..e17c6d2 100644
- spin_lock_irqsave(&rtc_lock, flags);
efi_call_phys_prelog();
status = efi_call_phys2(efi_phys.get_time, tm, tc);
status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm),
virt_to_phys(tc));
efi_call_phys_epilog();
- spin_unlock_irqrestore(&rtc_lock, flags);
return status;

View File

@ -1,163 +0,0 @@
A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html)
discusses warnings that occur during a suspend/resume cycle. The driver
attempts to read the firmware file before userspace is ready, leading to the
following warning:
WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420()
For rtl8192cu, the problem is fixed by storing the firmware in a global buffer
rather than one allocated per device. The usage count is increased when
suspending and decreased when resuming. This way, the firmware is retained
through a suspend/resume cycle, and does not have to be reread.
This patch should fix the bug reported in
https://bugzilla.redhat.com/show_bug.cgi?id=771002.
Note: This patch also touches rtl8192ce as the "firmware" loaded message
is now printed in the wrong place.
Note: This patch also touches rtl8192ce as the "firmware" loaded message
is now printed in the wrong place.
Reported-by: Mohammed Arafa <bugzilla@xxxxxxxxxxxx>
Reported-by: Dave Jones <davej@xxxxxxxxxx>
Signed-off-by: Larry Finger <Larry.Finger@xxxxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Stable <stable@xxxxxxxxxxxxxxx>
---
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 -
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 +
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++----
3 files changed, 49 insertions(+), 11 deletions(-)
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500
@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_
u32 fwsize;
enum version_8192c version = rtlhal->version;
- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
if (!rtlhal->pfirmware)
return 1;
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
rtlpriv->rtlhal.fwsize = firmware->size;
release_firmware(firmware);
+ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name);
return 0;
}
--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -43,6 +43,8 @@
#include "hw.h"
#include <linux/vmalloc.h>
#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/types.h>
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
MODULE_AUTHOR("Ziv Huang <ziv_huang@realtek.com>");
@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
+static char *rtl8192cu_firmware; /* pointer to firmware */
+static int firmware_size;
+static atomic_t usage_count;
+
static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i
rtlpriv->dm.disable_framebursting = false;
rtlpriv->dm.thermalvalue = 0;
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
- if (!rtlpriv->rtlhal.pfirmware) {
+
+ if (rtl8192cu_firmware) {
+ /* firmware already loaded - true for suspend/resume
+ * and multiple instances of the device */
+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware;
+ rtlpriv->rtlhal.fwsize = firmware_size;
+ return 0;
+ }
+ rtl8192cu_firmware = vzalloc(0x4000);
+ if (!rtl8192cu_firmware) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Can't alloc buffer for fw.\n"));
return 1;
}
+
/* request fw */
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
rtlpriv->io.dev);
@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i
release_firmware(firmware);
return 1;
}
- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+ pr_info("rtl8192cu: Loaded firmware from file %s\n",
+ rtlpriv->cfg->fw_name);
+ memcpy(rtl8192cu_firmware, firmware->data, firmware->size);
+ firmware_size = firmware->size;
rtlpriv->rtlhal.fwsize = firmware->size;
+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware;
release_firmware(firmware);
+ atomic_inc(&usage_count);
return 0;
}
@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- if (rtlpriv->rtlhal.pfirmware) {
- vfree(rtlpriv->rtlhal.pfirmware);
+ atomic_dec(&usage_count);
+ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) {
+ vfree(rtl8192cu_firmware);
+ rtl8192cu_firmware = NULL;
rtlpriv->rtlhal.pfirmware = NULL;
}
}
+#ifdef CONFIG_PM_SLEEP
+static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf,
+ pm_message_t message)
+{
+ /* Increase usage_count to Save loaded fw across suspend/resume */
+ atomic_inc(&usage_count);
+ return 0;
+}
+
+static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf)
+{
+ atomic_dec(&usage_count); /* after resume, decrease usage count */
+ return 0;
+}
+#endif
+
static struct rtl_hal_ops rtl8192cu_hal_ops = {
.init_sw_vars = rtl92cu_init_sw_vars,
.deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive
.disconnect = rtl_usb_disconnect,
.id_table = rtl8192c_usb_ids,
-#ifdef CONFIG_PM
- /* .suspend = rtl_usb_suspend, */
- /* .resume = rtl_usb_resume, */
- /* .reset_resume = rtl8192c_resume, */
-#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_SLEEP
+ .suspend = rtl8192cu_usb_suspend,
+ .resume = rtl8192cu_usb_resume,
+#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_AUTOSUSPEND
.supports_autosuspend = 1,
#endif

View File

@ -1,3 +1,3 @@
364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz
2fed18362598429cc0669c01123290ff compat-wireless-2012-01-09.tar.bz2
62ac6ac9b870162f693ecf5e8606423a patch-3.2.1.xz
1c3dd34fa219420a4cbed1e573d253e7 patch-3.3-rc1.xz

View File

@ -1,239 +0,0 @@
From: Neil Horman <nhorman@tuxdriver.com>
Date: Thu, 6 Oct 2011 18:08:18 +0000 (-0400)
Subject: PCI/sysfs: add per pci device msi[x] irq listing (v5)
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci.git;a=commitdiff_plain;h=933aa5c1f69aa650f59ba783307fc7ed7cc5fafa
PCI/sysfs: add per pci device msi[x] irq listing (v5)
This patch adds a per-pci-device subdirectory in sysfs called:
/sys/bus/pci/devices/<device>/msi_irqs
This sub-directory exports the set of msi vectors allocated by a given
pci device, by creating a numbered sub-directory for each vector beneath
msi_irqs. For each vector various attributes can be exported.
Currently the only attribute is called mode, which tracks the
operational mode of that vector (msi vs. msix)
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 349ecf2..34f5110 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -66,6 +66,24 @@ Description:
re-discover previously removed devices.
Depends on CONFIG_HOTPLUG.
+What: /sys/bus/pci/devices/.../msi_irqs/
+Date: September, 2011
+Contact: Neil Horman <nhorman@tuxdriver.com>
+Description:
+ The /sys/devices/.../msi_irqs directory contains a variable set
+ of sub-directories, with each sub-directory being named after a
+ corresponding msi irq vector allocated to that device. Each
+ numbered sub-directory N contains attributes of that irq.
+ Note that this directory is not created for device drivers which
+ do not support msi irqs
+
+What: /sys/bus/pci/devices/.../msi_irqs/<N>/mode
+Date: September 2011
+Contact: Neil Horman <nhorman@tuxdriver.com>
+Description:
+ This attribute indicates the mode that the irq vector named by
+ the parent directory is in (msi vs. msix)
+
What: /sys/bus/pci/devices/.../remove
Date: January 2009
Contact: Linux PCI developers <linux-pci@vger.kernel.org>
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2f10328..73613e2 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -322,6 +322,8 @@ static void free_msi_irqs(struct pci_dev *dev)
if (list_is_last(&entry->list, &dev->msi_list))
iounmap(entry->mask_base);
}
+ kobject_del(&entry->kobj);
+ kobject_put(&entry->kobj);
list_del(&entry->list);
kfree(entry);
}
@@ -402,6 +404,98 @@ void pci_restore_msi_state(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_restore_msi_state);
+
+#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr)
+#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj)
+
+struct msi_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr,
+ const char *buf, size_t count);
+};
+
+static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi");
+}
+
+static ssize_t msi_irq_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct msi_attribute *attribute = to_msi_attr(attr);
+ struct msi_desc *entry = to_msi_desc(kobj);
+
+ if (!attribute->show)
+ return -EIO;
+
+ return attribute->show(entry, attribute, buf);
+}
+
+static const struct sysfs_ops msi_irq_sysfs_ops = {
+ .show = msi_irq_attr_show,
+};
+
+static struct msi_attribute mode_attribute =
+ __ATTR(mode, S_IRUGO, show_msi_mode, NULL);
+
+
+struct attribute *msi_irq_default_attrs[] = {
+ &mode_attribute.attr,
+ NULL
+};
+
+void msi_kobj_release(struct kobject *kobj)
+{
+ struct msi_desc *entry = to_msi_desc(kobj);
+
+ pci_dev_put(entry->dev);
+}
+
+static struct kobj_type msi_irq_ktype = {
+ .release = msi_kobj_release,
+ .sysfs_ops = &msi_irq_sysfs_ops,
+ .default_attrs = msi_irq_default_attrs,
+};
+
+static int populate_msi_sysfs(struct pci_dev *pdev)
+{
+ struct msi_desc *entry;
+ struct kobject *kobj;
+ int ret;
+ int count = 0;
+
+ pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj);
+ if (!pdev->msi_kset)
+ return -ENOMEM;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ kobj = &entry->kobj;
+ kobj->kset = pdev->msi_kset;
+ pci_dev_get(pdev);
+ ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL,
+ "%u", entry->irq);
+ if (ret)
+ goto out_unroll;
+
+ count++;
+ }
+
+ return 0;
+
+out_unroll:
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ if (!count)
+ break;
+ kobject_del(&entry->kobj);
+ kobject_put(&entry->kobj);
+ count--;
+ }
+ return ret;
+}
+
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -453,6 +547,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
return ret;
}
+ ret = populate_msi_sysfs(dev);
+ if (ret) {
+ msi_mask_irq(entry, mask, ~mask);
+ free_msi_irqs(dev);
+ return ret;
+ }
+
/* Set MSI enabled bits */
pci_intx_for_msi(dev, 0);
msi_set_enable(dev, pos, 1);
@@ -573,6 +674,12 @@ static int msix_capability_init(struct pci_dev *dev,
msix_program_entries(dev, entries);
+ ret = populate_msi_sysfs(dev);
+ if (ret) {
+ ret = 0;
+ goto error;
+ }
+
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
@@ -731,6 +838,8 @@ void pci_disable_msi(struct pci_dev *dev)
pci_msi_shutdown(dev);
free_msi_irqs(dev);
+ kset_unregister(dev->msi_kset);
+ dev->msi_kset = NULL;
}
EXPORT_SYMBOL(pci_disable_msi);
@@ -829,6 +938,8 @@ void pci_disable_msix(struct pci_dev *dev)
pci_msix_shutdown(dev);
free_msi_irqs(dev);
+ kset_unregister(dev->msi_kset);
+ dev->msi_kset = NULL;
}
EXPORT_SYMBOL(pci_disable_msix);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 05acced..ce93a34 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -1,6 +1,7 @@
#ifndef LINUX_MSI_H
#define LINUX_MSI_H
+#include <linux/kobject.h>
#include <linux/list.h>
struct msi_msg {
@@ -44,6 +45,8 @@ struct msi_desc {
/* Last set MSI message */
struct msi_msg msg;
+
+ struct kobject kobj;
};
/*
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7cda65b..84225c7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -336,6 +336,7 @@ struct pci_dev {
struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
#ifdef CONFIG_PCI_MSI
struct list_head msi_list;
+ struct kset *msi_kset;
#endif
struct pci_vpd *vpd;
#ifdef CONFIG_PCI_ATS