From: Greg Kroah-Hartman Date: Wed, 11 Jul 2012 21:41:47 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.0.37~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=28f85fac92962b8d814315e5b68d75d82854484e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: ipheth-add-support-for-ipad.patch iwlwifi-remove-log_event-debugfs-file-debugging-is-disabled.patch lockd-pass-network-namespace-to-creation-and-destruction-routines.patch mac80211-fix-queues-stuck-issue-with-ht-bandwidth-change.patch nfs-hard-code-init_net-for-nfs-callback-transports.patch sunrpc-move-per-net-operations-from-svc_destroy.patch sunrpc-new-svc_bind-routine-introduced.patch --- diff --git a/queue-3.4/ipheth-add-support-for-ipad.patch b/queue-3.4/ipheth-add-support-for-ipad.patch new file mode 100644 index 00000000000..5adfe957836 --- /dev/null +++ b/queue-3.4/ipheth-add-support-for-ipad.patch @@ -0,0 +1,41 @@ +From 6de0298ec9c1edaf330b71b57346241ece8f3346 Mon Sep 17 00:00:00 2001 +From: Davide Gerhard +Date: Mon, 25 Jun 2012 09:04:47 +0200 +Subject: ipheth: add support for iPad + +From: Davide Gerhard + +commit 6de0298ec9c1edaf330b71b57346241ece8f3346 upstream. + +This adds support for the iPad to the ipheth driver. +(product id = 0x129a) + +Signed-off-by: Davide Gerhard +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/ipheth.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -59,6 +59,7 @@ + #define USB_PRODUCT_IPHONE_3G 0x1292 + #define USB_PRODUCT_IPHONE_3GS 0x1294 + #define USB_PRODUCT_IPHONE_4 0x1297 ++#define USB_PRODUCT_IPAD 0x129a + #define USB_PRODUCT_IPHONE_4_VZW 0x129c + #define USB_PRODUCT_IPHONE_4S 0x12a0 + +@@ -101,6 +102,10 @@ static struct usb_device_id ipheth_table + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( ++ USB_VENDOR_APPLE, USB_PRODUCT_IPAD, ++ IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, ++ IPHETH_USBINTF_PROTO) }, ++ { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, diff --git a/queue-3.4/iwlwifi-remove-log_event-debugfs-file-debugging-is-disabled.patch b/queue-3.4/iwlwifi-remove-log_event-debugfs-file-debugging-is-disabled.patch new file mode 100644 index 00000000000..692e897b110 --- /dev/null +++ b/queue-3.4/iwlwifi-remove-log_event-debugfs-file-debugging-is-disabled.patch @@ -0,0 +1,63 @@ +From: Johannes Berg +Date: Wed, 20 Jun 2012 08:46:25 +0200 +Subject: iwlwifi: remove log_event debugfs file debugging is disabled + +From: Johannes Berg + +commit 882b7b7d11d65e8eccce738f1ce97cdfdb998f9f upstream. + +When debugging is disabled, the event log functions aren't +functional in the way that the debugfs file expects. This +leads to the debugfs access crashing. Since the event log +functions aren't functional then, remove the debugfs file +when CONFIG_IWLWIFI_DEBUG is not set. + +Reported-by: Lekensteyn +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +[bwh: Backported to 3.2: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -2000,6 +2000,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(s + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); + } + ++#ifdef CONFIG_IWLWIFI_DEBUG + static ssize_t iwl_dbgfs_log_event_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +@@ -2037,6 +2038,7 @@ static ssize_t iwl_dbgfs_log_event_write + + return count; + } ++#endif + + static ssize_t iwl_dbgfs_interrupt_read(struct file *file, + char __user *user_buf, +@@ -2164,7 +2166,9 @@ static ssize_t iwl_dbgfs_fh_reg_read(str + return ret; + } + ++#ifdef CONFIG_IWLWIFI_DEBUG + DEBUGFS_READ_WRITE_FILE_OPS(log_event); ++#endif + DEBUGFS_READ_WRITE_FILE_OPS(interrupt); + DEBUGFS_READ_FILE_OPS(fh_reg); + DEBUGFS_READ_FILE_OPS(rx_queue); +@@ -2180,7 +2184,9 @@ static int iwl_trans_pcie_dbgfs_register + { + DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); + DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); ++#ifdef CONFIG_IWLWIFI_DEBUG + DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); ++#endif + DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); diff --git a/queue-3.4/lockd-pass-network-namespace-to-creation-and-destruction-routines.patch b/queue-3.4/lockd-pass-network-namespace-to-creation-and-destruction-routines.patch new file mode 100644 index 00000000000..ee18dd8f844 --- /dev/null +++ b/queue-3.4/lockd-pass-network-namespace-to-creation-and-destruction-routines.patch @@ -0,0 +1,156 @@ +From bfields@redhat.com Wed Jul 11 14:38:33 2012 +From: "J. Bruce Fields" +Date: Mon, 25 Jun 2012 16:40:07 -0400 +Subject: Lockd: pass network namespace to creation and destruction routines +To: stable@vger.kernel.org +Cc: Stanislav Kinsbursky , linux-nfs@vger.kernel.org, "J. Bruce Fields" +Message-ID: <1340656810-13752-1-git-send-email-bfields@redhat.com> + + +From: Stanislav Kinsbursky + +upstream commit e3f70eadb7dddfb5a2bb9afff7abfc6ee17a29d0. + +v2: dereference of most probably already released nlm_host removed in +nlmclnt_done() and reclaimer(). + +These routines are called from locks reclaimer() kernel thread. This thread +works in "init_net" network context and currently relays on persence on lockd +thread and it's per-net resources. Thus lockd_up() and lockd_down() can't relay +on current network context. So let's pass corrent one into them. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman +--- + fs/lockd/clntlock.c | 13 ++++++++----- + fs/lockd/svc.c | 7 +++---- + fs/nfsd/nfssvc.c | 6 +++--- + include/linux/lockd/bind.h | 4 ++-- + 4 files changed, 16 insertions(+), 14 deletions(-) + +--- a/fs/lockd/clntlock.c ++++ b/fs/lockd/clntlock.c +@@ -56,7 +56,7 @@ struct nlm_host *nlmclnt_init(const stru + u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; + int status; + +- status = lockd_up(); ++ status = lockd_up(nlm_init->net); + if (status < 0) + return ERR_PTR(status); + +@@ -65,7 +65,7 @@ struct nlm_host *nlmclnt_init(const stru + nlm_init->hostname, nlm_init->noresvport, + nlm_init->net); + if (host == NULL) { +- lockd_down(); ++ lockd_down(nlm_init->net); + return ERR_PTR(-ENOLCK); + } + +@@ -80,8 +80,10 @@ EXPORT_SYMBOL_GPL(nlmclnt_init); + */ + void nlmclnt_done(struct nlm_host *host) + { ++ struct net *net = host->net; ++ + nlmclnt_release_host(host); +- lockd_down(); ++ lockd_down(net); + } + EXPORT_SYMBOL_GPL(nlmclnt_done); + +@@ -220,11 +222,12 @@ reclaimer(void *ptr) + struct nlm_wait *block; + struct file_lock *fl, *next; + u32 nsmstate; ++ struct net *net = host->net; + + allow_signal(SIGKILL); + + down_write(&host->h_rwsem); +- lockd_up(); /* note: this cannot fail as lockd is already running */ ++ lockd_up(net); /* note: this cannot fail as lockd is already running */ + + dprintk("lockd: reclaiming locks for host %s\n", host->h_name); + +@@ -275,6 +278,6 @@ restart: + + /* Release host handle after use */ + nlmclnt_release_host(host); +- lockd_down(); ++ lockd_down(net); + return 0; + } +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -295,11 +295,10 @@ static void lockd_down_net(struct net *n + /* + * Bring up the lockd process if it's not already up. + */ +-int lockd_up(void) ++int lockd_up(struct net *net) + { + struct svc_serv *serv; + int error = 0; +- struct net *net = current->nsproxy->net_ns; + + mutex_lock(&nlmsvc_mutex); + /* +@@ -378,12 +377,12 @@ EXPORT_SYMBOL_GPL(lockd_up); + * Decrement the user count and bring down lockd if we're the last. + */ + void +-lockd_down(void) ++lockd_down(struct net *net) + { + mutex_lock(&nlmsvc_mutex); + if (nlmsvc_users) { + if (--nlmsvc_users) { +- lockd_down_net(current->nsproxy->net_ns); ++ lockd_down_net(net); + goto out; + } + } else { +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -220,7 +220,7 @@ static int nfsd_startup(unsigned short p + ret = nfsd_init_socks(port); + if (ret) + goto out_racache; +- ret = lockd_up(); ++ ret = lockd_up(&init_net); + if (ret) + goto out_racache; + ret = nfs4_state_start(); +@@ -229,7 +229,7 @@ static int nfsd_startup(unsigned short p + nfsd_up = true; + return 0; + out_lockd: +- lockd_down(); ++ lockd_down(&init_net); + out_racache: + nfsd_racache_shutdown(); + return ret; +@@ -246,7 +246,7 @@ static void nfsd_shutdown(void) + if (!nfsd_up) + return; + nfs4_state_shutdown(); +- lockd_down(); ++ lockd_down(&init_net); + nfsd_racache_shutdown(); + nfsd_up = false; + } +--- a/include/linux/lockd/bind.h ++++ b/include/linux/lockd/bind.h +@@ -54,7 +54,7 @@ extern void nlmclnt_done(struct nlm_host + + extern int nlmclnt_proc(struct nlm_host *host, int cmd, + struct file_lock *fl); +-extern int lockd_up(void); +-extern void lockd_down(void); ++extern int lockd_up(struct net *net); ++extern void lockd_down(struct net *net); + + #endif /* LINUX_LOCKD_BIND_H */ diff --git a/queue-3.4/mac80211-fix-queues-stuck-issue-with-ht-bandwidth-change.patch b/queue-3.4/mac80211-fix-queues-stuck-issue-with-ht-bandwidth-change.patch new file mode 100644 index 00000000000..ea1e1eaf665 --- /dev/null +++ b/queue-3.4/mac80211-fix-queues-stuck-issue-with-ht-bandwidth-change.patch @@ -0,0 +1,84 @@ +From johannes@sipsolutions.net Wed Jul 11 14:39:54 2012 +From: Johannes Berg +Date: Wed, 27 Jun 2012 18:11:56 +0200 +Subject: mac80211: fix queues stuck issue with HT bandwidth change +To: stable@vger.kernel.org +Message-ID: <1340813516.11012.46.camel@jlt3.sipsolutions.net> + + +From: Johannes Berg + +No upstream commit, the buggy code was removed in 3.5 in commit +7213cf2cb0dfbb4d6b55a1da000d34338f76c0e3 and others. + +Rajkumar changed code for handling channel switching in +mac80211 to stop the queues in + + commit 7cc44ed48d0ec0937c1f098642540b6c9ca38de5 + Author: Rajkumar Manoharan + Date: Fri Sep 16 15:32:34 2011 +0530 + + mac80211: Fix regression on queue stop during 2040 bss change + +which went into 3.2. In the 3.4 cycle, Paul's change + + commit 3117bbdb7899d43927c8ce4fe885ab7c1231c121 + Author: Paul Stewart + Date: Tue Mar 13 07:46:18 2012 -0700 + + mac80211: Don't let regulatory make us deaf + +went in and changed the TX/RX enable logic, but now +the conditions for stopping and restarting the queues +were different so that now, if the AP changes between +20/40 MHz bandwidth, it can happen that we stop but +never restart the queues. This breaks the connection +and the module actually has to be reloaded to get it +back to work. + +Fix this by making sure the queues are always started +when they were stopped. + +Reported-by: Florian Manschwetus +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/mlme.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -187,7 +187,7 @@ static u32 ieee80211_enable_ht(struct ie + u32 changed = 0; + int hti_cfreq; + u16 ht_opmode; +- bool enable_ht = true; ++ bool enable_ht = true, queues_stopped = false; + enum nl80211_channel_type prev_chantype; + enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; + enum nl80211_channel_type tx_channel_type; +@@ -254,6 +254,7 @@ static u32 ieee80211_enable_ht(struct ie + */ + ieee80211_stop_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); ++ queues_stopped = true; + + /* flush out all packets */ + synchronize_net(); +@@ -272,12 +273,12 @@ static u32 ieee80211_enable_ht(struct ie + IEEE80211_RC_HT_CHANGED, + tx_channel_type); + rcu_read_unlock(); +- +- if (beacon_htcap_ie) +- ieee80211_wake_queues_by_reason(&sdata->local->hw, +- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + } + ++ if (queues_stopped) ++ ieee80211_wake_queues_by_reason(&sdata->local->hw, ++ IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); ++ + ht_opmode = le16_to_cpu(hti->operation_mode); + + /* if bss configuration changed store the new one */ diff --git a/queue-3.4/nfs-hard-code-init_net-for-nfs-callback-transports.patch b/queue-3.4/nfs-hard-code-init_net-for-nfs-callback-transports.patch new file mode 100644 index 00000000000..9da7b804bdd --- /dev/null +++ b/queue-3.4/nfs-hard-code-init_net-for-nfs-callback-transports.patch @@ -0,0 +1,81 @@ +From bfields@redhat.com Wed Jul 11 14:39:26 2012 +From: "J. Bruce Fields" +Date: Mon, 25 Jun 2012 16:40:10 -0400 +Subject: NFS: hard-code init_net for NFS callback transports +To: stable@vger.kernel.org +Cc: Stanislav Kinsbursky , linux-nfs@vger.kernel.org, "J. Bruce Fields" +Message-ID: <1340656810-13752-4-git-send-email-bfields@redhat.com> + + +From: Stanislav Kinsbursky + +upstream commit 12918b10d59e975fd5241eef03ef9e6d5ea3dcfe. + +In case of destroying mount namespace on child reaper exit, nsproxy is zeroed +to the point already. So, dereferencing of it is invalid. +This patch hard-code "init_net" for all network namespace references for NFS +callback services. This will be fixed with proper NFS callback +containerization. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/callback.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + + #include + +@@ -107,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv, + { + int ret; + +- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET, ++ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret <= 0) + goto out_err; +@@ -115,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv, + dprintk("NFS: Callback listener port = %u (af %u)\n", + nfs_callback_tcpport, PF_INET); + +- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET6, ++ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret > 0) { + nfs_callback_tcpport6 = ret; +@@ -184,7 +183,7 @@ nfs41_callback_up(struct svc_serv *serv, + * fore channel connection. + * Returns the input port (0) and sets the svc_serv bc_xprt on success + */ +- ret = svc_create_xprt(serv, "tcp-bc", xprt->xprt_net, PF_INET, 0, ++ ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, + SVC_SOCK_ANONYMOUS); + if (ret < 0) { + rqstp = ERR_PTR(ret); +@@ -254,7 +253,7 @@ int nfs_callback_up(u32 minorversion, st + char svc_name[12]; + int ret = 0; + int minorversion_setup; +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = &init_net; + + mutex_lock(&nfs_callback_mutex); + if (cb_info->users++ || cb_info->task != NULL) { +@@ -330,7 +329,7 @@ void nfs_callback_down(int minorversion) + cb_info->users--; + if (cb_info->users == 0 && cb_info->task != NULL) { + kthread_stop(cb_info->task); +- svc_shutdown_net(cb_info->serv, current->nsproxy->net_ns); ++ svc_shutdown_net(cb_info->serv, &init_net); + svc_exit_thread(cb_info->rqst); + cb_info->serv = NULL; + cb_info->rqst = NULL; diff --git a/queue-3.4/series b/queue-3.4/series index ab6203ba97f..8a435f2c7fb 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -153,3 +153,10 @@ usb-option-add-mediatek-product-ids.patch usb-add-support-for-root-hub-port-status-cas.patch xhci-fix-hang-on-back-to-back-set-tr-deq-ptr-commands.patch pci-ehci-fix-crash-during-suspend-on-asus-computers.patch +ipheth-add-support-for-ipad.patch +lockd-pass-network-namespace-to-creation-and-destruction-routines.patch +sunrpc-new-svc_bind-routine-introduced.patch +sunrpc-move-per-net-operations-from-svc_destroy.patch +nfs-hard-code-init_net-for-nfs-callback-transports.patch +mac80211-fix-queues-stuck-issue-with-ht-bandwidth-change.patch +iwlwifi-remove-log_event-debugfs-file-debugging-is-disabled.patch diff --git a/queue-3.4/sunrpc-move-per-net-operations-from-svc_destroy.patch b/queue-3.4/sunrpc-move-per-net-operations-from-svc_destroy.patch new file mode 100644 index 00000000000..4b394bfa20f --- /dev/null +++ b/queue-3.4/sunrpc-move-per-net-operations-from-svc_destroy.patch @@ -0,0 +1,284 @@ +From bfields@redhat.com Wed Jul 11 14:39:15 2012 +From: "J. Bruce Fields" +Date: Mon, 25 Jun 2012 16:40:09 -0400 +Subject: SUNRPC: move per-net operations from svc_destroy() +To: stable@vger.kernel.org +Cc: Stanislav Kinsbursky , linux-nfs@vger.kernel.org, "J. Bruce Fields" +Message-ID: <1340656810-13752-3-git-send-email-bfields@redhat.com> + + +From: Stanislav Kinsbursky + +upstream commit 786185b5f8abefa6a8a16695bb4a59c164d5a071. + +The idea is to separate service destruction and per-net operations, +because these are two different things and the mix looks ugly. + +Notes: + +1) For NFS server this patch looks ugly (sorry for that). But these +place will be rewritten soon during NFSd containerization. + +2) LockD per-net counter increase int lockd_up() was moved prior to +make_socks() to make lockd_down_net() call safe in case of error. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman +--- + fs/lockd/svc.c | 27 +++++++++++++++------------ + fs/nfs/callback.c | 3 +++ + fs/nfsd/nfsctl.c | 12 +++++++++--- + fs/nfsd/nfssvc.c | 14 ++++++++++++++ + net/sunrpc/svc.c | 4 ---- + 5 files changed, 41 insertions(+), 19 deletions(-) + +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -257,7 +257,7 @@ static int lockd_up_net(struct net *net) + struct svc_serv *serv = nlmsvc_rqst->rq_server; + int error; + +- if (ln->nlmsvc_users) ++ if (ln->nlmsvc_users++) + return 0; + + error = svc_rpcb_setup(serv, net); +@@ -272,6 +272,7 @@ static int lockd_up_net(struct net *net) + err_socks: + svc_rpcb_cleanup(serv, net); + err_rpcb: ++ ln->nlmsvc_users--; + return error; + } + +@@ -299,6 +300,7 @@ int lockd_up(struct net *net) + { + struct svc_serv *serv; + int error = 0; ++ struct lockd_net *ln = net_generic(net, lockd_net_id); + + mutex_lock(&nlmsvc_mutex); + /* +@@ -330,9 +332,11 @@ int lockd_up(struct net *net) + goto destroy_and_out; + } + ++ ln->nlmsvc_users++; ++ + error = make_socks(serv, net); + if (error < 0) +- goto destroy_and_out; ++ goto err_start; + + /* + * Create the kernel thread and wait for it to start. +@@ -344,7 +348,7 @@ int lockd_up(struct net *net) + printk(KERN_WARNING + "lockd_up: svc_rqst allocation failed, error=%d\n", + error); +- goto destroy_and_out; ++ goto err_start; + } + + svc_sock_update_bufs(serv); +@@ -358,7 +362,7 @@ int lockd_up(struct net *net) + nlmsvc_rqst = NULL; + printk(KERN_WARNING + "lockd_up: kthread_run failed, error=%d\n", error); +- goto destroy_and_out; ++ goto err_start; + } + + /* +@@ -368,14 +372,14 @@ int lockd_up(struct net *net) + destroy_and_out: + svc_destroy(serv); + out: +- if (!error) { +- struct lockd_net *ln = net_generic(net, lockd_net_id); +- +- ln->nlmsvc_users++; ++ if (!error) + nlmsvc_users++; +- } + mutex_unlock(&nlmsvc_mutex); + return error; ++ ++err_start: ++ lockd_down_net(net); ++ goto destroy_and_out; + } + EXPORT_SYMBOL_GPL(lockd_up); + +@@ -386,11 +390,10 @@ void + lockd_down(struct net *net) + { + mutex_lock(&nlmsvc_mutex); ++ lockd_down_net(net); + if (nlmsvc_users) { +- if (--nlmsvc_users) { +- lockd_down_net(net); ++ if (--nlmsvc_users) + goto out; +- } + } else { + printk(KERN_ERR "lockd_down: no users! task=%p\n", + nlmsvc_task); +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -314,6 +314,8 @@ out_err: + dprintk("NFS: Couldn't create callback socket or server thread; " + "err = %d\n", ret); + cb_info->users--; ++ if (serv) ++ svc_shutdown_net(serv, net); + goto out; + } + +@@ -328,6 +330,7 @@ void nfs_callback_down(int minorversion) + cb_info->users--; + if (cb_info->users == 0 && cb_info->task != NULL) { + kthread_stop(cb_info->task); ++ svc_shutdown_net(cb_info->serv, current->nsproxy->net_ns); + svc_exit_thread(cb_info->rqst); + cb_info->serv = NULL; + cb_info->rqst = NULL; +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -651,6 +651,7 @@ static ssize_t __write_ports_addfd(char + { + char *mesg = buf; + int fd, err; ++ struct net *net = &init_net; + + err = get_int(&mesg, &fd); + if (err != 0 || fd < 0) +@@ -662,6 +663,8 @@ static ssize_t __write_ports_addfd(char + + err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); + if (err < 0) { ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + return err; + } +@@ -699,6 +702,7 @@ static ssize_t __write_ports_addxprt(cha + char transport[16]; + struct svc_xprt *xprt; + int port, err; ++ struct net *net = &init_net; + + if (sscanf(buf, "%15s %4u", transport, &port) != 2) + return -EINVAL; +@@ -710,12 +714,12 @@ static ssize_t __write_ports_addxprt(cha + if (err != 0) + return err; + +- err = svc_create_xprt(nfsd_serv, transport, &init_net, ++ err = svc_create_xprt(nfsd_serv, transport, net, + PF_INET, port, SVC_SOCK_ANONYMOUS); + if (err < 0) + goto out_err; + +- err = svc_create_xprt(nfsd_serv, transport, &init_net, ++ err = svc_create_xprt(nfsd_serv, transport, net, + PF_INET6, port, SVC_SOCK_ANONYMOUS); + if (err < 0 && err != -EAFNOSUPPORT) + goto out_close; +@@ -724,12 +728,14 @@ static ssize_t __write_ports_addxprt(cha + nfsd_serv->sv_nrthreads--; + return 0; + out_close: +- xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port); ++ xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port); + if (xprt != NULL) { + svc_close_xprt(xprt); + svc_xprt_put(xprt); + } + out_err: ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + return err; + } +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -382,6 +382,7 @@ int nfsd_set_nrthreads(int n, int *nthre + int i = 0; + int tot = 0; + int err = 0; ++ struct net *net = &init_net; + + WARN_ON(!mutex_is_locked(&nfsd_mutex)); + +@@ -426,6 +427,9 @@ int nfsd_set_nrthreads(int n, int *nthre + if (err) + break; + } ++ ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + + return err; +@@ -441,6 +445,7 @@ nfsd_svc(unsigned short port, int nrserv + { + int error; + bool nfsd_up_before; ++ struct net *net = &init_net; + + mutex_lock(&nfsd_mutex); + dprintk("nfsd: creating service\n"); +@@ -473,6 +478,8 @@ out_shutdown: + if (error < 0 && !nfsd_up_before) + nfsd_shutdown(); + out_destroy: ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); /* Release server */ + out: + mutex_unlock(&nfsd_mutex); +@@ -556,6 +563,9 @@ nfsd(void *vrqstp) + nfsdstats.th_cnt --; + + out: ++ if (rqstp->rq_server->sv_nrthreads == 1) ++ svc_shutdown_net(rqstp->rq_server, &init_net); ++ + /* Release the thread */ + svc_exit_thread(rqstp); + +@@ -668,8 +678,12 @@ int nfsd_pool_stats_open(struct inode *i + int nfsd_pool_stats_release(struct inode *inode, struct file *file) + { + int ret = seq_release(inode, file); ++ struct net *net = &init_net; ++ + mutex_lock(&nfsd_mutex); + /* this function really, really should have been called svc_put() */ ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + mutex_unlock(&nfsd_mutex); + return ret; +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -537,8 +537,6 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); + void + svc_destroy(struct svc_serv *serv) + { +- struct net *net = current->nsproxy->net_ns; +- + dprintk("svc: svc_destroy(%s, %d)\n", + serv->sv_program->pg_name, + serv->sv_nrthreads); +@@ -553,8 +551,6 @@ svc_destroy(struct svc_serv *serv) + + del_timer_sync(&serv->sv_temptimer); + +- svc_shutdown_net(serv, net); +- + /* + * The last user is gone and thus all sockets have to be destroyed to + * the point. Check this. diff --git a/queue-3.4/sunrpc-new-svc_bind-routine-introduced.patch b/queue-3.4/sunrpc-new-svc_bind-routine-introduced.patch new file mode 100644 index 00000000000..93935bef582 --- /dev/null +++ b/queue-3.4/sunrpc-new-svc_bind-routine-introduced.patch @@ -0,0 +1,182 @@ +From bfields@redhat.com Wed Jul 11 14:39:03 2012 +From: "J. Bruce Fields" +Date: Mon, 25 Jun 2012 16:40:08 -0400 +Subject: SUNRPC: new svc_bind() routine introduced +To: stable@vger.kernel.org +Cc: Stanislav Kinsbursky , linux-nfs@vger.kernel.org, "J. Bruce Fields" +Message-ID: <1340656810-13752-2-git-send-email-bfields@redhat.com> + + +From: Stanislav Kinsbursky + +upstream commit 9793f7c88937e7ac07305ab1af1a519225836823. + +This new routine is responsible for service registration in a specified +network context. + +The idea is to separate service creation from per-net operations. + +Note also: since registering service with svc_bind() can fail, the +service will be destroyed and during destruction it will try to +unregister itself from rpcbind. In this case unregistration has to be +skipped. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman +--- + fs/lockd/svc.c | 6 ++++++ + fs/nfs/callback.c | 8 ++++++++ + fs/nfsd/nfssvc.c | 9 +++++++++ + include/linux/sunrpc/svc.h | 1 + + net/sunrpc/rpcb_clnt.c | 12 +++++++----- + net/sunrpc/svc.c | 19 ++++++++++--------- + 6 files changed, 41 insertions(+), 14 deletions(-) + +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -324,6 +324,12 @@ int lockd_up(struct net *net) + goto out; + } + ++ error = svc_bind(serv, net); ++ if (error < 0) { ++ printk(KERN_WARNING "lockd_up: bind service failed\n"); ++ goto destroy_and_out; ++ } ++ + error = make_socks(serv, net); + if (error < 0) + goto destroy_and_out; +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + +@@ -253,6 +254,7 @@ int nfs_callback_up(u32 minorversion, st + char svc_name[12]; + int ret = 0; + int minorversion_setup; ++ struct net *net = current->nsproxy->net_ns; + + mutex_lock(&nfs_callback_mutex); + if (cb_info->users++ || cb_info->task != NULL) { +@@ -265,6 +267,12 @@ int nfs_callback_up(u32 minorversion, st + goto out_err; + } + ++ ret = svc_bind(serv, net); ++ if (ret < 0) { ++ printk(KERN_WARNING "NFS: bind callback service failed\n"); ++ goto out_err; ++ } ++ + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, + serv, xprt, &rqstp, &callback_svc); + if (!minorversion_setup) { +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -330,6 +331,8 @@ static int nfsd_get_default_max_blksize( + + int nfsd_create_serv(void) + { ++ int error; ++ + WARN_ON(!mutex_is_locked(&nfsd_mutex)); + if (nfsd_serv) { + svc_get(nfsd_serv); +@@ -343,6 +346,12 @@ int nfsd_create_serv(void) + if (nfsd_serv == NULL) + return -ENOMEM; + ++ error = svc_bind(nfsd_serv, current->nsproxy->net_ns); ++ if (error < 0) { ++ svc_destroy(nfsd_serv); ++ return error; ++ } ++ + set_max_drc(); + do_gettimeofday(&nfssvc_boot); /* record boot time */ + return 0; +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -416,6 +416,7 @@ struct svc_procedure { + */ + int svc_rpcb_setup(struct svc_serv *serv, struct net *net); + void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); ++int svc_bind(struct svc_serv *serv, struct net *net); + struct svc_serv *svc_create(struct svc_program *, unsigned int, + void (*shutdown)(struct svc_serv *, struct net *net)); + struct svc_rqst *svc_prepare_thread(struct svc_serv *serv, +--- a/net/sunrpc/rpcb_clnt.c ++++ b/net/sunrpc/rpcb_clnt.c +@@ -180,14 +180,16 @@ void rpcb_put_local(struct net *net) + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + struct rpc_clnt *clnt = sn->rpcb_local_clnt; + struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; +- int shutdown; ++ int shutdown = 0; + + spin_lock(&sn->rpcb_clnt_lock); +- if (--sn->rpcb_users == 0) { +- sn->rpcb_local_clnt = NULL; +- sn->rpcb_local_clnt4 = NULL; ++ if (sn->rpcb_users) { ++ if (--sn->rpcb_users == 0) { ++ sn->rpcb_local_clnt = NULL; ++ sn->rpcb_local_clnt4 = NULL; ++ } ++ shutdown = !sn->rpcb_users; + } +- shutdown = !sn->rpcb_users; + spin_unlock(&sn->rpcb_clnt_lock); + + if (shutdown) { +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -407,6 +407,14 @@ static int svc_uses_rpcbind(struct svc_s + return 0; + } + ++int svc_bind(struct svc_serv *serv, struct net *net) ++{ ++ if (!svc_uses_rpcbind(serv)) ++ return 0; ++ return svc_rpcb_setup(serv, net); ++} ++EXPORT_SYMBOL_GPL(svc_bind); ++ + /* + * Create an RPC service + */ +@@ -471,15 +479,8 @@ __svc_create(struct svc_program *prog, u + spin_lock_init(&pool->sp_lock); + } + +- if (svc_uses_rpcbind(serv)) { +- if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { +- kfree(serv->sv_pools); +- kfree(serv); +- return NULL; +- } +- if (!serv->sv_shutdown) +- serv->sv_shutdown = svc_rpcb_cleanup; +- } ++ if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) ++ serv->sv_shutdown = svc_rpcb_cleanup; + + return serv; + }