From: Greg Kroah-Hartman Date: Thu, 27 Sep 2012 18:25:18 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.0.44~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3b288afbed4e9ae7da2c7b0837a49a88b3a44d66;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: fix-a-dead-loop-in-async_synchronize_full.patch libata-prevent-interface-errors-with-seagate-freeagent-goflex.patch media-cx25821-remove-bad-strcpy-to-read-only-char.patch media-lirc_sir-make-device-registration-work.patch mm-sparse-fix-usemap-allocation-above-node-descriptor-section.patch net-statically-initialize-init_net.dev_base_head.patch r8169-rxconfig-hack-for-the-8168evl.patch rds-set-correct-msg_namelen.patch sched-fix-race-in-task_group.patch --- diff --git a/queue-3.4/fix-a-dead-loop-in-async_synchronize_full.patch b/queue-3.4/fix-a-dead-loop-in-async_synchronize_full.patch new file mode 100644 index 00000000000..5cf952c519d --- /dev/null +++ b/queue-3.4/fix-a-dead-loop-in-async_synchronize_full.patch @@ -0,0 +1,94 @@ +From akpm@linux-foundation.org Thu Sep 27 10:42:06 2012 +From: Li Zhong +Date: Tue, 24 Jul 2012 15:02:49 -0700 +Subject: Fix a dead loop in async_synchronize_full() + +From: Li Zhong + +[Fixed upstream by commits 2955b47d2c1983998a8c5915cb96884e67f7cb53 and +a4683487f90bfe3049686fc5c566bdc1ad03ace6 from Dan Williams, but they are much +more intrusive than this tiny fix, according to Andrew - gregkh] + +This patch tries to fix a dead loop in async_synchronize_full(), which +could be seen when preemption is disabled on a single cpu machine. + +void async_synchronize_full(void) +{ + do { + async_synchronize_cookie(next_cookie); + } while (!list_empty(&async_running) || ! +list_empty(&async_pending)); +} + +async_synchronize_cookie() calls async_synchronize_cookie_domain() with +&async_running as the default domain to synchronize. + +However, there might be some works in the async_pending list from other +domains. On a single cpu system, without preemption, there is no chance +for the other works to finish, so async_synchronize_full() enters a dead +loop. + +It seems async_synchronize_full() wants to synchronize all entries in +all running lists(domains), so maybe we could just check the entry_count +to know whether all works are finished. + +Currently, async_synchronize_cookie_domain() expects a non-NULL running +list ( if NULL, there would be NULL pointer dereference ), so maybe a +NULL pointer could be used as an indication for the functions to +synchronize all works in all domains. + +Reported-by: Paul E. McKenney +Signed-off-by: Li Zhong +Tested-by: Paul E. McKenney +Tested-by: Christian Kujau +Cc: Andrew Morton +Cc: Dan Williams +Cc: Christian Kujau +Cc: Andrew Morton +Cc: Cong Wang +Signed-off-by: Greg Kroah-Hartman +--- + kernel/async.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/kernel/async.c b/kernel/async.c +index bd0c168..32d8dc9 100644 +--- a/kernel/async.c ++++ b/kernel/async.c +@@ -86,6 +86,13 @@ static async_cookie_t __lowest_in_progress(struct list_head *running) + { + struct async_entry *entry; + ++ if (!running) { /* just check the entry count */ ++ if (atomic_read(&entry_count)) ++ return 0; /* smaller than any cookie */ ++ else ++ return next_cookie; ++ } ++ + if (!list_empty(running)) { + entry = list_first_entry(running, + struct async_entry, list); +@@ -236,9 +243,7 @@ EXPORT_SYMBOL_GPL(async_schedule_domain); + */ + void async_synchronize_full(void) + { +- do { +- async_synchronize_cookie(next_cookie); +- } while (!list_empty(&async_running) || !list_empty(&async_pending)); ++ async_synchronize_cookie_domain(next_cookie, NULL); + } + EXPORT_SYMBOL_GPL(async_synchronize_full); + +@@ -258,7 +263,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain); + /** + * async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing + * @cookie: async_cookie_t to use as checkpoint +- * @running: running list to synchronize on ++ * @running: running list to synchronize on, NULL indicates all lists + * + * This function waits until all asynchronous function calls for the + * synchronization domain specified by the running list @list submitted +-- +1.7.9.5 + diff --git a/queue-3.4/libata-prevent-interface-errors-with-seagate-freeagent-goflex.patch b/queue-3.4/libata-prevent-interface-errors-with-seagate-freeagent-goflex.patch new file mode 100644 index 00000000000..fb35f391ba2 --- /dev/null +++ b/queue-3.4/libata-prevent-interface-errors-with-seagate-freeagent-goflex.patch @@ -0,0 +1,36 @@ +From c531077f40abc9f2129c4c83a30b3f8d6ce1c0e7 Mon Sep 17 00:00:00 2001 +From: Daniel J Blueman +Date: Mon, 23 Jul 2012 12:22:37 +0800 +Subject: libata: Prevent interface errors with Seagate FreeAgent GoFlex + +From: Daniel J Blueman + +commit c531077f40abc9f2129c4c83a30b3f8d6ce1c0e7 upstream. + +When using my Seagate FreeAgent GoFlex eSATAp external disk enclosure, +interface errors are always seen until 1.5Gbps is negotiated [1]. This +occurs using any disk in the enclosure, and when the disk is connected +directly with a generic passive eSATAp cable, we see stable 3Gbps +operation as expected. + +Blacklist 3Gbps mode to avoid dataloss and the ~30s delay bus reset +and renegotiation incurs. + +Signed-off-by: Daniel J Blueman +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4125,6 +4125,7 @@ static const struct ata_blacklist_entry + + /* Devices which aren't very happy with higher link speeds */ + { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, ++ { "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS, }, + + /* + * Devices which choke on SETXFER. Applies only if both the diff --git a/queue-3.4/media-cx25821-remove-bad-strcpy-to-read-only-char.patch b/queue-3.4/media-cx25821-remove-bad-strcpy-to-read-only-char.patch new file mode 100644 index 00000000000..6ccb2700c8f --- /dev/null +++ b/queue-3.4/media-cx25821-remove-bad-strcpy-to-read-only-char.patch @@ -0,0 +1,50 @@ +From c854d8883fec59332f0662917f8c94dcfb1c405d Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 18 Jul 2012 13:41:11 -0300 +Subject: media: cx25821: Remove bad strcpy to read-only char* + +From: Ezequiel Garcia + +commit c854d8883fec59332f0662917f8c94dcfb1c405d upstream. + +The strcpy was being used to set the name of the board. +This was both wrong and redundant, +since the destination char* was read-only and +the name is set statically at compile time. + +The type of the name field is changed to const char* +to prevent future errors. + +Reported-by: Radek Masin +Signed-off-by: Ezequiel Garcia +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/cx25821/cx25821-core.c | 3 --- + drivers/media/video/cx25821/cx25821.h | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/media/video/cx25821/cx25821-core.c ++++ b/drivers/media/video/cx25821/cx25821-core.c +@@ -912,9 +912,6 @@ static int cx25821_dev_setup(struct cx25 + list_add_tail(&dev->devlist, &cx25821_devlist); + mutex_unlock(&cx25821_devlist_mutex); + +- strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); +- strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); +- + if (dev->pci->device != 0x8210) { + pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); +--- a/drivers/media/video/cx25821/cx25821.h ++++ b/drivers/media/video/cx25821/cx25821.h +@@ -187,7 +187,7 @@ enum port { + }; + + struct cx25821_board { +- char *name; ++ const char *name; + enum port porta; + enum port portb; + enum port portc; diff --git a/queue-3.4/media-lirc_sir-make-device-registration-work.patch b/queue-3.4/media-lirc_sir-make-device-registration-work.patch new file mode 100644 index 00000000000..551650f1d48 --- /dev/null +++ b/queue-3.4/media-lirc_sir-make-device-registration-work.patch @@ -0,0 +1,129 @@ +From 4b71ca6bce8fab3d08c61bf330e781f957934ae1 Mon Sep 17 00:00:00 2001 +From: Jarod Wilson +Date: Mon, 4 Jun 2012 13:05:24 -0300 +Subject: media: lirc_sir: make device registration work + +From: Jarod Wilson + +commit 4b71ca6bce8fab3d08c61bf330e781f957934ae1 upstream. + +For one, the driver device pointer needs to be filled in, or the lirc core +will refuse to load the driver. And we really need to wire up all the +platform_device bits. This has been tested via the lirc sourceforge tree +and verified to work, been sitting there for months, finally getting +around to sending it. :\ + +Signed-off-by: Jarod Wilson +Signed-off-by: Mauro Carvalho Chehab +CC: Josh Boyer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/media/lirc/lirc_sir.c | 60 ++++++++++++++++++++++++++++++++-- + 1 file changed, 58 insertions(+), 2 deletions(-) + +--- a/drivers/staging/media/lirc/lirc_sir.c ++++ b/drivers/staging/media/lirc/lirc_sir.c +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + #ifdef LIRC_ON_SA1100 + #include + #ifdef CONFIG_SA1100_COLLIE +@@ -487,9 +488,11 @@ static struct lirc_driver driver = { + .owner = THIS_MODULE, + }; + ++static struct platform_device *lirc_sir_dev; + + static int init_chrdev(void) + { ++ driver.dev = &lirc_sir_dev->dev; + driver.minor = lirc_register_driver(&driver); + if (driver.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); +@@ -1215,20 +1218,71 @@ static int init_lirc_sir(void) + return 0; + } + ++static int __devinit lirc_sir_probe(struct platform_device *dev) ++{ ++ return 0; ++} ++ ++static int __devexit lirc_sir_remove(struct platform_device *dev) ++{ ++ return 0; ++} ++ ++static struct platform_driver lirc_sir_driver = { ++ .probe = lirc_sir_probe, ++ .remove = __devexit_p(lirc_sir_remove), ++ .driver = { ++ .name = "lirc_sir", ++ .owner = THIS_MODULE, ++ }, ++}; + + static int __init lirc_sir_init(void) + { + int retval; + ++ retval = platform_driver_register(&lirc_sir_driver); ++ if (retval) { ++ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register " ++ "failed!\n"); ++ return -ENODEV; ++ } ++ ++ lirc_sir_dev = platform_device_alloc("lirc_dev", 0); ++ if (!lirc_sir_dev) { ++ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc " ++ "failed!\n"); ++ retval = -ENOMEM; ++ goto pdev_alloc_fail; ++ } ++ ++ retval = platform_device_add(lirc_sir_dev); ++ if (retval) { ++ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add " ++ "failed!\n"); ++ retval = -ENODEV; ++ goto pdev_add_fail; ++ } ++ + retval = init_chrdev(); + if (retval < 0) +- return retval; ++ goto fail; ++ + retval = init_lirc_sir(); + if (retval) { + drop_chrdev(); +- return retval; ++ goto fail; + } ++ + return 0; ++ ++fail: ++ platform_device_del(lirc_sir_dev); ++pdev_add_fail: ++ platform_device_put(lirc_sir_dev); ++pdev_alloc_fail: ++ platform_driver_unregister(&lirc_sir_driver); ++ return retval; + } + + static void __exit lirc_sir_exit(void) +@@ -1236,6 +1290,8 @@ static void __exit lirc_sir_exit(void) + drop_hardware(); + drop_chrdev(); + drop_port(); ++ platform_device_unregister(lirc_sir_dev); ++ platform_driver_unregister(&lirc_sir_driver); + printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); + } + diff --git a/queue-3.4/mm-sparse-fix-usemap-allocation-above-node-descriptor-section.patch b/queue-3.4/mm-sparse-fix-usemap-allocation-above-node-descriptor-section.patch new file mode 100644 index 00000000000..858647f16a3 --- /dev/null +++ b/queue-3.4/mm-sparse-fix-usemap-allocation-above-node-descriptor-section.patch @@ -0,0 +1,58 @@ +From 99ab7b19440a72ebdf225f99b20f8ef40decee86 Mon Sep 17 00:00:00 2001 +From: Yinghai Lu +Date: Wed, 11 Jul 2012 14:02:53 -0700 +Subject: mm: sparse: fix usemap allocation above node descriptor section + +From: Yinghai Lu + +commit 99ab7b19440a72ebdf225f99b20f8ef40decee86 upstream. + +After commit f5bf18fa22f8 ("bootmem/sparsemem: remove limit constraint +in alloc_bootmem_section"), usemap allocations may easily be placed +outside the optimal section that holds the node descriptor, even if +there is space available in that section. This results in unnecessary +hotplug dependencies that need to have the node unplugged before the +section holding the usemap. + +The reason is that the bootmem allocator doesn't guarantee a linear +search starting from the passed allocation goal but may start out at a +much higher address absent an upper limit. + +Fix this by trying the allocation with the limit at the section end, +then retry without if that fails. This keeps the fix from f5bf18fa22f8 +of not panicking if the allocation does not fit in the section, but +still makes sure to try to stay within the section at first. + +[rewritten massively by Johannes to apply to 3.4] + +Signed-off-by: Yinghai Lu +Signed-off-by: Johannes Weiner +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + +--- + mm/bootmem.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/mm/bootmem.c ++++ b/mm/bootmem.c +@@ -766,13 +766,17 @@ void * __init alloc_bootmem_section(unsi + unsigned long section_nr) + { + bootmem_data_t *bdata; +- unsigned long pfn, goal; ++ unsigned long pfn, goal, limit; + + pfn = section_nr_to_pfn(section_nr); + goal = pfn << PAGE_SHIFT; ++ limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; + bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; + +- return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0); ++ if (goal + size > limit) ++ limit = 0; ++ ++ return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); + } + #endif + diff --git a/queue-3.4/net-statically-initialize-init_net.dev_base_head.patch b/queue-3.4/net-statically-initialize-init_net.dev_base_head.patch new file mode 100644 index 00000000000..73478bb0ebd --- /dev/null +++ b/queue-3.4/net-statically-initialize-init_net.dev_base_head.patch @@ -0,0 +1,49 @@ +From 734b65417b24d6eea3e3d7457e1f11493890ee1d Mon Sep 17 00:00:00 2001 +From: "Rustad, Mark D" +Date: Wed, 18 Jul 2012 09:06:07 +0000 +Subject: net: Statically initialize init_net.dev_base_head + +From: "Rustad, Mark D" + +commit 734b65417b24d6eea3e3d7457e1f11493890ee1d upstream. + +This change eliminates an initialization-order hazard most +recently seen when netprio_cgroup is built into the kernel. + +With thanks to Eric Dumazet for catching a bug. + +Signed-off-by: Mark Rustad +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/core/dev.c | 3 ++- + net/core/net_namespace.c | 4 +++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6303,7 +6303,8 @@ static struct hlist_head *netdev_create_ + /* Initialize per network namespace state */ + static int __net_init netdev_init(struct net *net) + { +- INIT_LIST_HEAD(&net->dev_base_head); ++ if (net != &init_net) ++ INIT_LIST_HEAD(&net->dev_base_head); + + net->dev_name_head = netdev_create_hash(); + if (net->dev_name_head == NULL) +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -25,7 +25,9 @@ static DEFINE_MUTEX(net_mutex); + LIST_HEAD(net_namespace_list); + EXPORT_SYMBOL_GPL(net_namespace_list); + +-struct net init_net; ++struct net init_net = { ++ .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), ++}; + EXPORT_SYMBOL(init_net); + + #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ diff --git a/queue-3.4/r8169-rxconfig-hack-for-the-8168evl.patch b/queue-3.4/r8169-rxconfig-hack-for-the-8168evl.patch new file mode 100644 index 00000000000..0552390db38 --- /dev/null +++ b/queue-3.4/r8169-rxconfig-hack-for-the-8168evl.patch @@ -0,0 +1,44 @@ +From eb2dc35d99028b698cdedba4f5522bc43e576bd2 Mon Sep 17 00:00:00 2001 +From: Francois Romieu +Date: Wed, 20 Jun 2012 12:09:18 +0000 +Subject: r8169: RxConfig hack for the 8168evl. + +From: Francois Romieu + +commit eb2dc35d99028b698cdedba4f5522bc43e576bd2 upstream. + +The 8168evl (RTL_GIGA_MAC_VER_34) based Gigabyte GA-990FXA motherboards +are very prone to NETDEV watchdog problems without this change. See +https://bugzilla.kernel.org/show_bug.cgi?id=42899 for instance. + +I don't know why it *works*. It's depressingly effective though. + +For the record: +- the problem may go along IOMMU (AMD-Vi) errors but it really looks + like a red herring. +- the patch sets the RX_MULTI_EN bit. If the 8168c doc is any guide, + the chipset now fetches several Rx descriptors at a time. +- long ago the driver ignored the RX_MULTI_EN bit. + e542a2269f232d61270ceddd42b73a4348dee2bb changed the RxConfig + settings. Whatever the problem it's now labeled a regression. +- Realtek's own driver can identify two different 8168evl devices + (CFG_METHOD_16 and CFG_METHOD_17) where the r8169 driver only + sees one. It sucks. + +Signed-off-by: Francois Romieu +Signed-off-by: David S. Miller + +--- + drivers/net/ethernet/realtek/r8169.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -3737,6 +3737,7 @@ static void rtl_init_rxcfg(struct rtl816 + case RTL_GIGA_MAC_VER_22: + case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: ++ case RTL_GIGA_MAC_VER_34: + RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); + break; + default: diff --git a/queue-3.4/rds-set-correct-msg_namelen.patch b/queue-3.4/rds-set-correct-msg_namelen.patch new file mode 100644 index 00000000000..6688b59c67e --- /dev/null +++ b/queue-3.4/rds-set-correct-msg_namelen.patch @@ -0,0 +1,220 @@ +From 06b6a1cf6e776426766298d055bb3991957d90a7 Mon Sep 17 00:00:00 2001 +From: Weiping Pan +Date: Mon, 23 Jul 2012 10:37:48 +0800 +Subject: rds: set correct msg_namelen + +From: Weiping Pan + +commit 06b6a1cf6e776426766298d055bb3991957d90a7 upstream. + +Jay Fenlason (fenlason@redhat.com) found a bug, +that recvfrom() on an RDS socket can return the contents of random kernel +memory to userspace if it was called with a address length larger than +sizeof(struct sockaddr_in). +rds_recvmsg() also fails to set the addr_len paramater properly before +returning, but that's just a bug. +There are also a number of cases wher recvfrom() can return an entirely bogus +address. Anything in rds_recvmsg() that returns a non-negative value but does +not go through the "sin = (struct sockaddr_in *)msg->msg_name;" code path +at the end of the while(1) loop will return up to 128 bytes of kernel memory +to userspace. + +And I write two test programs to reproduce this bug, you will see that in +rds_server, fromAddr will be overwritten and the following sock_fd will be +destroyed. +Yes, it is the programmer's fault to set msg_namelen incorrectly, but it is +better to make the kernel copy the real length of address to user space in +such case. + +How to run the test programs ? +I test them on 32bit x86 system, 3.5.0-rc7. + +1 compile +gcc -o rds_client rds_client.c +gcc -o rds_server rds_server.c + +2 run ./rds_server on one console + +3 run ./rds_client on another console + +4 you will see something like: +server is waiting to receive data... +old socket fd=3 +server received data from client:data from client +msg.msg_namelen=32 +new socket fd=-1067277685 +sendmsg() +: Bad file descriptor + +/***************** rds_client.c ********************/ + +int main(void) +{ + int sock_fd; + struct sockaddr_in serverAddr; + struct sockaddr_in toAddr; + char recvBuffer[128] = "data from client"; + struct msghdr msg; + struct iovec iov; + + sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); + if (sock_fd < 0) { + perror("create socket error\n"); + exit(1); + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + serverAddr.sin_port = htons(4001); + + if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { + perror("bind() error\n"); + close(sock_fd); + exit(1); + } + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + toAddr.sin_port = htons(4000); + msg.msg_name = &toAddr; + msg.msg_namelen = sizeof(toAddr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = strlen(recvBuffer) + 1; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + if (sendmsg(sock_fd, &msg, 0) == -1) { + perror("sendto() error\n"); + close(sock_fd); + exit(1); + } + + printf("client send data:%s\n", recvBuffer); + + memset(recvBuffer, '\0', 128); + + msg.msg_name = &toAddr; + msg.msg_namelen = sizeof(toAddr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = 128; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + if (recvmsg(sock_fd, &msg, 0) == -1) { + perror("recvmsg() error\n"); + close(sock_fd); + exit(1); + } + + printf("receive data from server:%s\n", recvBuffer); + + close(sock_fd); + + return 0; +} + +/***************** rds_server.c ********************/ + +int main(void) +{ + struct sockaddr_in fromAddr; + int sock_fd; + struct sockaddr_in serverAddr; + unsigned int addrLen; + char recvBuffer[128]; + struct msghdr msg; + struct iovec iov; + + sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); + if(sock_fd < 0) { + perror("create socket error\n"); + exit(0); + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + serverAddr.sin_port = htons(4000); + if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { + perror("bind error\n"); + close(sock_fd); + exit(1); + } + + printf("server is waiting to receive data...\n"); + msg.msg_name = &fromAddr; + + /* + * I add 16 to sizeof(fromAddr), ie 32, + * and pay attention to the definition of fromAddr, + * recvmsg() will overwrite sock_fd, + * since kernel will copy 32 bytes to userspace. + * + * If you just use sizeof(fromAddr), it works fine. + * */ + msg.msg_namelen = sizeof(fromAddr) + 16; + /* msg.msg_namelen = sizeof(fromAddr); */ + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = 128; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + while (1) { + printf("old socket fd=%d\n", sock_fd); + if (recvmsg(sock_fd, &msg, 0) == -1) { + perror("recvmsg() error\n"); + close(sock_fd); + exit(1); + } + printf("server received data from client:%s\n", recvBuffer); + printf("msg.msg_namelen=%d\n", msg.msg_namelen); + printf("new socket fd=%d\n", sock_fd); + strcat(recvBuffer, "--data from server"); + if (sendmsg(sock_fd, &msg, 0) == -1) { + perror("sendmsg()\n"); + close(sock_fd); + exit(1); + } + } + + close(sock_fd); + return 0; +} + +Signed-off-by: Weiping Pan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/rds/recv.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -410,6 +410,8 @@ int rds_recvmsg(struct kiocb *iocb, stru + + rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + ++ msg->msg_namelen = 0; ++ + if (msg_flags & MSG_OOB) + goto out; + +@@ -485,6 +487,7 @@ int rds_recvmsg(struct kiocb *iocb, stru + sin->sin_port = inc->i_hdr.h_sport; + sin->sin_addr.s_addr = inc->i_saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ msg->msg_namelen = sizeof(*sin); + } + break; + } diff --git a/queue-3.4/sched-fix-race-in-task_group.patch b/queue-3.4/sched-fix-race-in-task_group.patch new file mode 100644 index 00000000000..8ebf51873f3 --- /dev/null +++ b/queue-3.4/sched-fix-race-in-task_group.patch @@ -0,0 +1,152 @@ +From 8323f26ce3425460769605a6aece7a174edaa7d1 Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Fri, 22 Jun 2012 13:36:05 +0200 +Subject: sched: Fix race in task_group() + +From: Peter Zijlstra + +commit 8323f26ce3425460769605a6aece7a174edaa7d1 upstream. + +Stefan reported a crash on a kernel before a3e5d1091c1 ("sched: +Don't call task_group() too many times in set_task_rq()"), he +found the reason to be that the multiple task_group() +invocations in set_task_rq() returned different values. + +Looking at all that I found a lack of serialization and plain +wrong comments. + +The below tries to fix it using an extra pointer which is +updated under the appropriate scheduler locks. Its not pretty, +but I can't really see another way given how all the cgroup +stuff works. + +Reported-and-tested-by: Stefan Bader +Signed-off-by: Peter Zijlstra +Link: http://lkml.kernel.org/r/1340364965.18025.71.camel@twins +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/init_task.h | 12 +++++++++++- + include/linux/sched.h | 5 ++++- + kernel/sched/core.c | 9 ++++++++- + kernel/sched/sched.h | 23 ++++++++++------------- + 4 files changed, 33 insertions(+), 16 deletions(-) + +--- a/include/linux/init_task.h ++++ b/include/linux/init_task.h +@@ -123,8 +123,17 @@ extern struct group_info init_groups; + + extern struct cred init_cred; + ++extern struct task_group root_task_group; ++ ++#ifdef CONFIG_CGROUP_SCHED ++# define INIT_CGROUP_SCHED(tsk) \ ++ .sched_task_group = &root_task_group, ++#else ++# define INIT_CGROUP_SCHED(tsk) ++#endif ++ + #ifdef CONFIG_PERF_EVENTS +-# define INIT_PERF_EVENTS(tsk) \ ++# define INIT_PERF_EVENTS(tsk) \ + .perf_event_mutex = \ + __MUTEX_INITIALIZER(tsk.perf_event_mutex), \ + .perf_event_list = LIST_HEAD_INIT(tsk.perf_event_list), +@@ -161,6 +170,7 @@ extern struct cred init_cred; + }, \ + .tasks = LIST_HEAD_INIT(tsk.tasks), \ + INIT_PUSHABLE_TASKS(tsk) \ ++ INIT_CGROUP_SCHED(tsk) \ + .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ + .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ + .real_parent = &tsk, \ +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1279,6 +1279,9 @@ struct task_struct { + const struct sched_class *sched_class; + struct sched_entity se; + struct sched_rt_entity rt; ++#ifdef CONFIG_CGROUP_SCHED ++ struct task_group *sched_task_group; ++#endif + + #ifdef CONFIG_PREEMPT_NOTIFIERS + /* list of struct preempt_notifier: */ +@@ -2744,7 +2747,7 @@ extern int sched_group_set_rt_period(str + extern long sched_group_rt_period(struct task_group *tg); + extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); + #endif +-#endif ++#endif /* CONFIG_CGROUP_SCHED */ + + extern int task_can_switch_user(struct user_struct *up, + struct task_struct *tsk); +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1098,7 +1098,7 @@ void set_task_cpu(struct task_struct *p, + * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. + * + * sched_move_task() holds both and thus holding either pins the cgroup, +- * see set_task_rq(). ++ * see task_group(). + * + * Furthermore, all task_rq users should acquire both locks, see + * task_rq_lock(). +@@ -7427,6 +7427,7 @@ void sched_destroy_group(struct task_gro + */ + void sched_move_task(struct task_struct *tsk) + { ++ struct task_group *tg; + int on_rq, running; + unsigned long flags; + struct rq *rq; +@@ -7441,6 +7442,12 @@ void sched_move_task(struct task_struct + if (unlikely(running)) + tsk->sched_class->put_prev_task(rq, tsk); + ++ tg = container_of(task_subsys_state_check(tsk, cpu_cgroup_subsys_id, ++ lockdep_is_held(&tsk->sighand->siglock)), ++ struct task_group, css); ++ tg = autogroup_task_group(tsk, tg); ++ tsk->sched_task_group = tg; ++ + #ifdef CONFIG_FAIR_GROUP_SCHED + if (tsk->sched_class->task_move_group) + tsk->sched_class->task_move_group(tsk, on_rq); +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -536,22 +536,19 @@ DECLARE_PER_CPU(int, sd_llc_id); + /* + * Return the group to which this tasks belongs. + * +- * We use task_subsys_state_check() and extend the RCU verification with +- * pi->lock and rq->lock because cpu_cgroup_attach() holds those locks for each +- * task it moves into the cgroup. Therefore by holding either of those locks, +- * we pin the task to the current cgroup. ++ * We cannot use task_subsys_state() and friends because the cgroup ++ * subsystem changes that value before the cgroup_subsys::attach() method ++ * is called, therefore we cannot pin it and might observe the wrong value. ++ * ++ * The same is true for autogroup's p->signal->autogroup->tg, the autogroup ++ * core changes this before calling sched_move_task(). ++ * ++ * Instead we use a 'copy' which is updated from sched_move_task() while ++ * holding both task_struct::pi_lock and rq::lock. + */ + static inline struct task_group *task_group(struct task_struct *p) + { +- struct task_group *tg; +- struct cgroup_subsys_state *css; +- +- css = task_subsys_state_check(p, cpu_cgroup_subsys_id, +- lockdep_is_held(&p->pi_lock) || +- lockdep_is_held(&task_rq(p)->lock)); +- tg = container_of(css, struct task_group, css); +- +- return autogroup_task_group(p, tg); ++ return p->sched_task_group; + } + + /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ diff --git a/queue-3.4/series b/queue-3.4/series index 383bb5d64a0..66f860364cf 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -174,3 +174,12 @@ bluetooth-add-support-for-apple-vendor-specific-devices.patch bluetooth-fix-use-after-free-bug-in-smp.patch bluetooth-change-signature-of-smp_conn_security.patch bluetooth-fix-sending-a-hci-authorization-request-over-le-links.patch +net-statically-initialize-init_net.dev_base_head.patch +media-cx25821-remove-bad-strcpy-to-read-only-char.patch +fix-a-dead-loop-in-async_synchronize_full.patch +rds-set-correct-msg_namelen.patch +libata-prevent-interface-errors-with-seagate-freeagent-goflex.patch +r8169-rxconfig-hack-for-the-8168evl.patch +sched-fix-race-in-task_group.patch +mm-sparse-fix-usemap-allocation-above-node-descriptor-section.patch +media-lirc_sir-make-device-registration-work.patch