X-Git-Url: http://git.pld-linux.org/?a=blobdiff_plain;f=kernel-regressions.patch;h=b26e1c44b9f5cef1263998896a9a83b870a08c14;hb=d27ab633e92338fec1ed18d5338747efdfa7f1d1;hp=7b249dd65886fd0b31cfacd6b299fd4ddf91329c;hpb=3b04b1f3bc2d06883f25d9491e5234872e416910;p=packages%2Fkernel.git diff --git a/kernel-regressions.patch b/kernel-regressions.patch index 7b249dd6..b26e1c44 100644 --- a/kernel-regressions.patch +++ b/kernel-regressions.patch @@ -1,288 +1,3 @@ -From jlayton@redhat.com Thu Dec 11 08:49:55 2008 -From: Jeff Layton -Date: Wed, 10 Dec 2008 06:44:29 -0500 -Subject: cifs: fix a regression in cifs umount codepath -To: greg@kroah.com, stable@kernel.org -Cc: smfrench@gmail.com, shirishp@us.ibm.com, sjayaraman@suse.de -Message-ID: <1228909469-438-1-git-send-email-jlayton@redhat.com> - -From: Jeff Layton - -backport of 469ee614aaa367d9cde01cbdd2027212f56c6cc6 upstream. - -Several cifs patches were added to 2.6.27.8 to fix some races in the -mount/umount codepath. When this was done, a couple of prerequisite -patches were missed causing a minor regression. - -When the last cifs mount to a server goes away, the kthread that manages -the socket is supposed to come down. The patches that went into 2.6.27.8 -removed the kthread_stop calls that used to take down these threads, but -left the thread function expecting them. This made the thread stay up -even after the last mount was gone. - -This patch should fix up this regression and also prevent a possible -race where a dead task could be signalled. - -Signed-off-by: Jeff Layton -Cc: Suresh Jayaraman -Acked-by: Steve French -Signed-off-by: Greg Kroah-Hartman - ---- - fs/cifs/connect.c | 36 +++++++++++++++++++++--------------- - 1 file changed, 21 insertions(+), 15 deletions(-) - ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -128,7 +128,7 @@ cifs_reconnect(struct TCP_Server_Info *s - struct mid_q_entry *mid_entry; - - spin_lock(&GlobalMid_Lock); -- if (kthread_should_stop()) { -+ if (server->tcpStatus == CifsExiting) { - /* the demux thread will exit normally - next time through the loop */ - spin_unlock(&GlobalMid_Lock); -@@ -182,7 +182,8 @@ cifs_reconnect(struct TCP_Server_Info *s - spin_unlock(&GlobalMid_Lock); - up(&server->tcpSem); - -- while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { -+ while ((server->tcpStatus != CifsExiting) && -+ (server->tcpStatus != CifsGood)) { - try_to_freeze(); - if (server->addr.sockAddr6.sin6_family == AF_INET6) { - rc = ipv6_connect(&server->addr.sockAddr6, -@@ -200,7 +201,7 @@ cifs_reconnect(struct TCP_Server_Info *s - } else { - atomic_inc(&tcpSesReconnectCount); - spin_lock(&GlobalMid_Lock); -- if (!kthread_should_stop()) -+ if (server->tcpStatus != CifsExiting) - server->tcpStatus = CifsGood; - server->sequence_number = 0; - spin_unlock(&GlobalMid_Lock); -@@ -355,7 +356,7 @@ cifs_demultiplex_thread(struct TCP_Serve - GFP_KERNEL); - - set_freezable(); -- while (!kthread_should_stop()) { -+ while (server->tcpStatus != CifsExiting) { - if (try_to_freeze()) - continue; - if (bigbuf == NULL) { -@@ -396,7 +397,7 @@ incomplete_rcv: - kernel_recvmsg(csocket, &smb_msg, - &iov, 1, pdu_length, 0 /* BB other flags? */); - -- if (kthread_should_stop()) { -+ if (server->tcpStatus == CifsExiting) { - break; - } else if (server->tcpStatus == CifsNeedReconnect) { - cFYI(1, ("Reconnect after server stopped responding")); -@@ -527,7 +528,7 @@ incomplete_rcv: - total_read += length) { - length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, - pdu_length - total_read, 0); -- if (kthread_should_stop() || -+ if ((server->tcpStatus == CifsExiting) || - (length == -EINTR)) { - /* then will exit */ - reconnect = 2; -@@ -661,14 +662,6 @@ multi_t2_fnd: - spin_unlock(&GlobalMid_Lock); - wake_up_all(&server->response_q); - -- /* don't exit until kthread_stop is called */ -- set_current_state(TASK_UNINTERRUPTIBLE); -- while (!kthread_should_stop()) { -- schedule(); -- set_current_state(TASK_UNINTERRUPTIBLE); -- } -- set_current_state(TASK_RUNNING); -- - /* check if we have blocked requests that need to free */ - /* Note that cifs_max_pending is normally 50, but - can be set at module install time to as little as two */ -@@ -764,6 +757,7 @@ multi_t2_fnd: - read_unlock(&cifs_tcp_ses_lock); - - kfree(server->hostname); -+ task_to_wake = xchg(&server->tsk, NULL); - kfree(server); - - length = atomic_dec_return(&tcpSesAllocCount); -@@ -771,6 +765,16 @@ multi_t2_fnd: - mempool_resize(cifs_req_poolp, length + cifs_min_rcv, - GFP_KERNEL); - -+ /* if server->tsk was NULL then wait for a signal before exiting */ -+ if (!task_to_wake) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ while (!signal_pending(current)) { -+ schedule(); -+ set_current_state(TASK_INTERRUPTIBLE); -+ } -+ set_current_state(TASK_RUNNING); -+ } -+ - return 0; - } - -@@ -2310,7 +2314,7 @@ cifs_mount(struct super_block *sb, struc - /* on error free sesinfo and tcon struct if needed */ - mount_fail_check: - if (rc) { -- /* If find_unc succeeded then rc == 0 so we can not end */ -+ /* If find_unc succeeded then rc == 0 so we can not end */ - /* up accidently freeing someone elses tcon struct */ - if (tcon) - cifs_put_tcon(tcon); -@@ -3715,8 +3719,10 @@ int cifs_setup_session(unsigned int xid, - cERROR(1, ("Send error in SessSetup = %d", rc)); - } else { - cFYI(1, ("CIFS Session Established successfully")); -+ spin_lock(&GlobalMid_Lock); - pSesInfo->status = CifsGood; - pSesInfo->need_reconnect = false; -+ spin_unlock(&GlobalMid_Lock); - } - - ss_err_exit: -From 218d11a8b071b23b76c484fd5f72a4fe3306801e Mon Sep 17 00:00:00 2001 -From: Jonathan Corbet -Date: Fri, 5 Dec 2008 16:12:48 -0700 -Subject: Fix a race condition in FASYNC handling - -From: Jonathan Corbet - -commit 218d11a8b071b23b76c484fd5f72a4fe3306801e upstream. - -Changeset a238b790d5f99c7832f9b73ac8847025815b85f7 (Call fasync() -functions without the BKL) introduced a race which could leave -file->f_flags in a state inconsistent with what the underlying -driver/filesystem believes. Revert that change, and also fix the same -races in ioctl_fioasync() and ioctl_fionbio(). - -This is a minimal, short-term fix; the real fix will not involve the -BKL. - -Reported-by: Oleg Nesterov -Cc: Andi Kleen -Cc: Al Viro -Signed-off-by: Jonathan Corbet -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/fcntl.c | 7 +++++++ - fs/ioctl.c | 12 ++++++++---- - 2 files changed, 15 insertions(+), 4 deletions(-) - ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -175,6 +176,11 @@ static int setfl(int fd, struct file * f - if (error) - return error; - -+ /* -+ * We still need a lock here for now to keep multiple FASYNC calls -+ * from racing with each other. -+ */ -+ lock_kernel(); - if ((arg ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) { - error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); -@@ -185,6 +191,7 @@ static int setfl(int fd, struct file * f - - filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); - out: -+ unlock_kernel(); - return error; - } - ---- a/fs/ioctl.c -+++ b/fs/ioctl.c -@@ -123,11 +123,9 @@ static int ioctl_fioasync(unsigned int f - - /* Did FASYNC state change ? */ - if ((flag ^ filp->f_flags) & FASYNC) { -- if (filp->f_op && filp->f_op->fasync) { -- lock_kernel(); -+ if (filp->f_op && filp->f_op->fasync) - error = filp->f_op->fasync(fd, filp, on); -- unlock_kernel(); -- } else -+ else - error = -ENOTTY; - } - if (error) -@@ -163,11 +161,17 @@ int do_vfs_ioctl(struct file *filp, unsi - break; - - case FIONBIO: -+ /* BKL needed to avoid races tweaking f_flags */ -+ lock_kernel(); - error = ioctl_fionbio(filp, argp); -+ unlock_kernel(); - break; - - case FIOASYNC: -+ /* BKL needed to avoid races tweaking f_flags */ -+ lock_kernel(); - error = ioctl_fioasync(fd, filp, argp); -+ unlock_kernel(); - break; - - case FIOQSIZE: -From 49c50342c728344b79c8f9e8293637fe80ef5ad5 Mon Sep 17 00:00:00 2001 -From: Matt Mackall -Date: Tue, 9 Dec 2008 13:14:21 -0800 -Subject: pagemap: fix 32-bit pagemap regression - -From: Matt Mackall - -commit 49c50342c728344b79c8f9e8293637fe80ef5ad5 upstream. - -The large pages fix from bcf8039ed45 broke 32-bit pagemap by pulling the -pagemap entry code out into a function with the wrong return type. -Pagemap entries are 64 bits on all systems and unsigned long is only 32 -bits on 32-bit systems. - -Signed-off-by: Matt Mackall -Reported-by: Doug Graham -Cc: Alexey Dobriyan -Cc: Dave Hansen -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/proc/task_mmu.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -563,9 +563,9 @@ static u64 swap_pte_to_pagemap_entry(pte - return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); - } - --static unsigned long pte_to_pagemap_entry(pte_t pte) -+static u64 pte_to_pagemap_entry(pte_t pte) - { -- unsigned long pme = 0; -+ u64 pme = 0; - if (is_swap_pte(pte)) - pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte)) - | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; rom ae060e0b7bc071bd73dd5319b93c3344d9e10212 Mon Sep 17 00:00:00 2001 From: Manfred Spraul To: torvalds@linux-foundation.org @@ -333,3 +48,299 @@ index 7a785a0..1c4f928 100644 -- 1.5.6.5 +From: Trond Myklebust +Date: Thu, 20 Nov 2008 21:06:21 +0000 (-0500) +Subject: SUNRPC: Fix a performance regression in the RPC authentication code +X-Git-Tag: v2.6.28-rc6~4 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=23918b03060f6e572168fdde1798a905679d2e06 + +SUNRPC: Fix a performance regression in the RPC authentication code + +Fix a regression reported by Max Kellermann whereby kernel profiling +showed that his clients were spending 45% of their time in +rpcauth_lookup_credcache. + +It turns out that although his processes had identical uid/gid/groups, +generic_match() was failing to detect this, because the task->group_info +pointers were not shared. This again lead to the creation of a huge number +of identical credentials at the RPC layer. + +The regression is fixed by comparing the contents of task->group_info +if the actual pointers are not identical. + +Signed-off-by: Trond Myklebust +Signed-off-by: Linus Torvalds +--- + +diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c +index 744b79f..4028502 100644 +--- a/net/sunrpc/auth_generic.c ++++ b/net/sunrpc/auth_generic.c +@@ -133,13 +133,29 @@ static int + generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) + { + struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); ++ int i; + + if (gcred->acred.uid != acred->uid || + gcred->acred.gid != acred->gid || +- gcred->acred.group_info != acred->group_info || + gcred->acred.machine_cred != acred->machine_cred) +- return 0; ++ goto out_nomatch; ++ ++ /* Optimisation in the case where pointers are identical... */ ++ if (gcred->acred.group_info == acred->group_info) ++ goto out_match; ++ ++ /* Slow path... */ ++ if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) ++ goto out_nomatch; ++ for (i = 0; i < gcred->acred.group_info->ngroups; i++) { ++ if (GROUP_AT(gcred->acred.group_info, i) != ++ GROUP_AT(acred->group_info, i)) ++ goto out_nomatch; ++ } ++out_match: + return 1; ++out_nomatch: ++ return 0; + } + + void __init rpc_init_generic_auth(void) +From d238e150805a0710fa626f9a7f65816aa15b741c Mon Sep 17 00:00:00 2001 +From: Brian Rogers +Date: Fri, 4 Sep 2009 05:55:01 -0700 +Subject: [PATCH] Fix memory corruption during IR initialization for various tuner cards + +In two different places the IR_i2c_init_data structure is used to store some +data for particular cards that will later override the settings that would +otherwise be used by the ir-kbd-i2c driver in ir_probe(). The way those +settings get there is problematic: init_data is on the stack, and a pointer to +it is stored to be used after the function that sets it up returns. Not good. + +init_data might be overwritten by the time ir_probe() runs. ir_probe() will +then call ir_input_init(), which proceeds to fill out the dev->keybit bit +array with a 1 in the appropriate slot for every key on the tuner's remote. + +But if the keymap pointer now points to random garbage, that will be used +instead to determine where to write each 1. And since IR_KEYTAB_TYPE is u32, +it can be write millions of bits past the end of dev->keybit. Essentially +this bug writes a 1 to up to 128 random bits in memory, stopping early (and +oopsing) if or when it hits an invalid page. + +To fix this, I define a static IR_i2c_init_data struct for each card that +needs one rather than creating the data on the stack. This way, I can supply a +pointer that will remain valid. Also I don't have to allocate memory just to +store information that's already known at compile time and I don't have bother +freeing it, either. + +This fixes a regression caused by commit 4d7a2d6721. + +Signed-off-by: Brian Rogers +--- + drivers/media/video/em28xx/em28xx-cards.c | 36 +++++++++----- + drivers/media/video/saa7134/saa7134-input.c | 71 ++++++++++++++++++--------- + 2 files changed, 70 insertions(+), 37 deletions(-) + +diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c +index 1c2e544..be9a4e8 100644 +--- a/drivers/media/video/em28xx/em28xx-cards.c ++++ b/drivers/media/video/em28xx/em28xx-cards.c +@@ -2167,11 +2167,29 @@ static int em28xx_hint_board(struct em28xx *dev) + return -1; + } + ++static struct IR_i2c_init_data init_data_em28xx_terratec = { ++ .name = "i2c IR (EM28XX Terratec)", ++ .ir_codes = ir_codes_em_terratec, ++ .get_key = em28xx_get_key_terratec, ++}; ++ ++static struct IR_i2c_init_data init_data_em28xx_pinnacle = { ++ .name = "i2c IR (EM28XX Pinnacle PCTV)", ++ .ir_codes = ir_codes_pinnacle_grey, ++ .get_key = em28xx_get_key_pinnacle_usb_grey, ++}; ++ ++static struct IR_i2c_init_data init_data_em28xx_hauppauge = { ++ .name = "i2c IR (EM2840 Hauppauge)", ++ .ir_codes = ir_codes_hauppauge_new, ++ .get_key = em28xx_get_key_em_haup, ++}; ++ + /* ----------------------------------------------------------------------- */ + void em28xx_register_i2c_ir(struct em28xx *dev) + { + struct i2c_board_info info; +- struct IR_i2c_init_data init_data; ++ struct IR_i2c_init_data *init_data = NULL; + const unsigned short addr_list[] = { + 0x30, 0x47, I2C_CLIENT_END + }; +@@ -2180,7 +2198,6 @@ void em28xx_register_i2c_ir(struct em28xx *dev) + return; + + memset(&info, 0, sizeof(struct i2c_board_info)); +- memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + + /* detect & configure */ +@@ -2191,19 +2208,13 @@ void em28xx_register_i2c_ir(struct em28xx *dev) + break; + case (EM2800_BOARD_TERRATEC_CINERGY_200): + case (EM2820_BOARD_TERRATEC_CINERGY_250): +- init_data.ir_codes = ir_codes_em_terratec; +- init_data.get_key = em28xx_get_key_terratec; +- init_data.name = "i2c IR (EM28XX Terratec)"; ++ init_data = &init_data_em28xx_terratec; + break; + case (EM2820_BOARD_PINNACLE_USB_2): +- init_data.ir_codes = ir_codes_pinnacle_grey; +- init_data.get_key = em28xx_get_key_pinnacle_usb_grey; +- init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; ++ init_data = &init_data_em28xx_pinnacle; + break; + case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): +- init_data.ir_codes = ir_codes_hauppauge_new; +- init_data.get_key = em28xx_get_key_em_haup; +- init_data.name = "i2c IR (EM2840 Hauppauge)"; ++ init_data = &init_data_em28xx_hauppauge; + break; + case (EM2820_BOARD_MSI_VOX_USB_2): + break; +@@ -2215,8 +2226,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) + break; + } + +- if (init_data.name) +- info.platform_data = &init_data; ++ info.platform_data = init_data; + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + } + +diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c +index 6e219c2..bb17bb9 100644 +--- a/drivers/media/video/saa7134/saa7134-input.c ++++ b/drivers/media/video/saa7134/saa7134-input.c +@@ -682,10 +682,46 @@ void saa7134_input_fini(struct saa7134_dev *dev) + dev->remote = NULL; + } + ++static struct IR_i2c_init_data init_data_pinnacle_color = { ++ .name = "Pinnacle PCTV", ++ .get_key = get_key_pinnacle_color, ++ .ir_codes = ir_codes_pinnacle_color, ++}; ++ ++static struct IR_i2c_init_data init_data_pinnacle_grey = { ++ .name = "Pinnacle PCTV", ++ .get_key = get_key_pinnacle_grey, ++ .ir_codes = ir_codes_pinnacle_grey, ++}; ++ ++static struct IR_i2c_init_data init_data_purpletv = { ++ .name = "Purple TV", ++ .get_key = get_key_purpletv, ++ .ir_codes = ir_codes_purpletv, ++}; ++ ++static struct IR_i2c_init_data init_data_msi_tvanywhere_plus = { ++ .name = "MSI TV@nywhere Plus", ++ .get_key = get_key_msi_tvanywhere_plus, ++ .ir_codes = ir_codes_msi_tvanywhere_plus, ++}; ++ ++static struct IR_i2c_init_data init_data_hauppauge = { ++ .name = "HVR 1110", ++ .get_key = get_key_hvr1110, ++ .ir_codes = ir_codes_hauppauge_new, ++}; ++ ++static struct IR_i2c_init_data init_data_behold = { ++ .name = "BeholdTV", ++ .get_key = get_key_beholdm6xx, ++ .ir_codes = ir_codes_behold, ++}; ++ + void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + { + struct i2c_board_info info; +- struct IR_i2c_init_data init_data; ++ struct IR_i2c_init_data *init_data = NULL; + const unsigned short addr_list[] = { + 0x7a, 0x47, 0x71, 0x2d, + I2C_CLIENT_END +@@ -706,30 +742,22 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + } + + memset(&info, 0, sizeof(struct i2c_board_info)); +- memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + + switch (dev->board) { + case SAA7134_BOARD_PINNACLE_PCTV_110i: + case SAA7134_BOARD_PINNACLE_PCTV_310i: +- init_data.name = "Pinnacle PCTV"; +- if (pinnacle_remote == 0) { +- init_data.get_key = get_key_pinnacle_color; +- init_data.ir_codes = ir_codes_pinnacle_color; +- } else { +- init_data.get_key = get_key_pinnacle_grey; +- init_data.ir_codes = ir_codes_pinnacle_grey; +- } ++ if (pinnacle_remote == 0) ++ init_data = &init_data_pinnacle_color; ++ else ++ init_data = &init_data_pinnacle_grey; ++ info.addr = 0x47; + break; + case SAA7134_BOARD_UPMOST_PURPLE_TV: +- init_data.name = "Purple TV"; +- init_data.get_key = get_key_purpletv; +- init_data.ir_codes = ir_codes_purpletv; ++ init_data = &init_data_purpletv; + break; + case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: +- init_data.name = "MSI TV@nywhere Plus"; +- init_data.get_key = get_key_msi_tvanywhere_plus; +- init_data.ir_codes = ir_codes_msi_tvanywhere_plus; ++ init_data = &init_data_msi_tvanywhere_plus; + info.addr = 0x30; + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from +@@ -741,9 +769,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + (1 == rc) ? "yes" : "no"); + break; + case SAA7134_BOARD_HAUPPAUGE_HVR1110: +- init_data.name = "HVR 1110"; +- init_data.get_key = get_key_hvr1110; +- init_data.ir_codes = ir_codes_hauppauge_new; ++ init_data = &init_data_hauppauge; + break; + case SAA7134_BOARD_BEHOLD_607FM_MK3: + case SAA7134_BOARD_BEHOLD_607FM_MK5: +@@ -757,9 +783,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + case SAA7134_BOARD_BEHOLD_M63: + case SAA7134_BOARD_BEHOLD_M6_EXTRA: + case SAA7134_BOARD_BEHOLD_H6: +- init_data.name = "BeholdTV"; +- init_data.get_key = get_key_beholdm6xx; +- init_data.ir_codes = ir_codes_behold; ++ init_data = &init_data_behold; + break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: +@@ -767,8 +791,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + break; + } + +- if (init_data.name) +- info.platform_data = &init_data; ++ info.platform_data = init_data; + /* No need to probe if address is known */ + if (info.addr) { + i2c_new_device(&dev->i2c_adap, &info); +-- +1.6.3.3 +