diff mbox series

[RFC,v21,3/7] NFSD: move create/destroy of laundry_wq to init_nfsd and exit_nfsd

Message ID 1650739455-26096-4-git-send-email-dai.ngo@oracle.com (mailing list archive)
State New
Headers show
Series NFSD: Initial implementation of NFSv4 Courteous Server | expand

Commit Message

Dai Ngo April 23, 2022, 6:44 p.m. UTC
This patch moves create/destroy of laundry_wq from nfs4_state_start
and nfs4_state_shutdown_net to init_nfsd and exit_nfsd to prevent
the laundromat from being freed while a thread is processing a
conflicting lock.

Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
---
 fs/nfsd/nfs4state.c | 15 ++-------------
 fs/nfsd/nfsctl.c    |  6 ++++++
 fs/nfsd/nfsd.h      |  1 +
 3 files changed, 9 insertions(+), 13 deletions(-)

Comments

Dai Ngo April 25, 2022, 3:27 p.m. UTC | #1
This patch has problem to build with this error:

>> nfsctl.c:(.exit.text+0x0): undefined reference to `laundry_wq'
>> mipsel-linux-ld: nfsctl.c:(.exit.text+0x4): undefined reference to `laundry_wq'

This happens when CONFIG_NFSD is defined but CONFIG_NFSD_V4
is not. I think to fix this we need to also move the declaration
of laundry_wq from nfs4state.c to nfsctl.c. However this seems
odd since the laundry_wq is only used for v4, unless you have
any other suggestion.

-Dai

On 4/23/22 11:44 AM, Dai Ngo wrote:
> This patch moves create/destroy of laundry_wq from nfs4_state_start
> and nfs4_state_shutdown_net to init_nfsd and exit_nfsd to prevent
> the laundromat from being freed while a thread is processing a
> conflicting lock.
>
> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
> ---
>   fs/nfsd/nfs4state.c | 15 ++-------------
>   fs/nfsd/nfsctl.c    |  6 ++++++
>   fs/nfsd/nfsd.h      |  1 +
>   3 files changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index b08c132648b9..b70ba2eb5665 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -125,7 +125,7 @@ static void free_session(struct nfsd4_session *);
>   static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
>   static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
>   
> -static struct workqueue_struct *laundry_wq;
> +struct workqueue_struct *laundry_wq;
>   
>   static bool is_session_dead(struct nfsd4_session *ses)
>   {
> @@ -7798,22 +7798,12 @@ nfs4_state_start(void)
>   {
>   	int ret;
>   
> -	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
> -	if (laundry_wq == NULL) {
> -		ret = -ENOMEM;
> -		goto out;
> -	}
>   	ret = nfsd4_create_callback_queue();
>   	if (ret)
> -		goto out_free_laundry;
> +		return ret;
>   
>   	set_max_delegations();
>   	return 0;
> -
> -out_free_laundry:
> -	destroy_workqueue(laundry_wq);
> -out:
> -	return ret;
>   }
>   
>   void
> @@ -7850,7 +7840,6 @@ nfs4_state_shutdown_net(struct net *net)
>   void
>   nfs4_state_shutdown(void)
>   {
> -	destroy_workqueue(laundry_wq);
>   	nfsd4_destroy_callback_queue();
>   }
>   
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 16920e4512bd..884e873b46ad 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -1544,6 +1544,11 @@ static int __init init_nfsd(void)
>   	retval = register_cld_notifier();
>   	if (retval)
>   		goto out_free_all;
> +	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
> +	if (laundry_wq == NULL) {
> +		retval = -ENOMEM;
> +		goto out_free_all;
> +	}
>   	return 0;
>   out_free_all:
>   	unregister_pernet_subsys(&nfsd_net_ops);
> @@ -1566,6 +1571,7 @@ static int __init init_nfsd(void)
>   
>   static void __exit exit_nfsd(void)
>   {
> +	destroy_workqueue(laundry_wq);
>   	unregister_cld_notifier();
>   	unregister_pernet_subsys(&nfsd_net_ops);
>   	nfsd_drc_slab_free();
> diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
> index 23996c6ca75e..d41dcf1c4312 100644
> --- a/fs/nfsd/nfsd.h
> +++ b/fs/nfsd/nfsd.h
> @@ -72,6 +72,7 @@ extern unsigned long		nfsd_drc_max_mem;
>   extern unsigned long		nfsd_drc_mem_used;
>   
>   extern const struct seq_operations nfs_exports_op;
> +extern struct workqueue_struct *laundry_wq;
>   
>   /*
>    * Common void argument and result helpers
J. Bruce Fields April 25, 2022, 7:35 p.m. UTC | #2
On Mon, Apr 25, 2022 at 08:27:22AM -0700, dai.ngo@oracle.com wrote:
> This patch has problem to build with this error:
> 
> >>nfsctl.c:(.exit.text+0x0): undefined reference to `laundry_wq'
> >>mipsel-linux-ld: nfsctl.c:(.exit.text+0x4): undefined reference to `laundry_wq'
> 
> This happens when CONFIG_NFSD is defined but CONFIG_NFSD_V4
> is not. I think to fix this we need to also move the declaration
> of laundry_wq from nfs4state.c to nfsctl.c. However this seems
> odd since the laundry_wq is only used for v4, unless you have
> any other suggestion.

I'd just leave laundry_wq private to nfs4state.c.  Define
create_laundromat() and destroy_laundromat() in nfs4state.c too.  And in
nfsd.h, do the usual trick of defining no-op versions of those functions
in the non-v4 case.  (See e.g. what we do with nfsd4_init/free_slabs().)

--b.

> 
> -Dai
> 
> On 4/23/22 11:44 AM, Dai Ngo wrote:
> >This patch moves create/destroy of laundry_wq from nfs4_state_start
> >and nfs4_state_shutdown_net to init_nfsd and exit_nfsd to prevent
> >the laundromat from being freed while a thread is processing a
> >conflicting lock.
> >
> >Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
> >---
> >  fs/nfsd/nfs4state.c | 15 ++-------------
> >  fs/nfsd/nfsctl.c    |  6 ++++++
> >  fs/nfsd/nfsd.h      |  1 +
> >  3 files changed, 9 insertions(+), 13 deletions(-)
> >
> >diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> >index b08c132648b9..b70ba2eb5665 100644
> >--- a/fs/nfsd/nfs4state.c
> >+++ b/fs/nfsd/nfs4state.c
> >@@ -125,7 +125,7 @@ static void free_session(struct nfsd4_session *);
> >  static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
> >  static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
> >-static struct workqueue_struct *laundry_wq;
> >+struct workqueue_struct *laundry_wq;
> >  static bool is_session_dead(struct nfsd4_session *ses)
> >  {
> >@@ -7798,22 +7798,12 @@ nfs4_state_start(void)
> >  {
> >  	int ret;
> >-	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
> >-	if (laundry_wq == NULL) {
> >-		ret = -ENOMEM;
> >-		goto out;
> >-	}
> >  	ret = nfsd4_create_callback_queue();
> >  	if (ret)
> >-		goto out_free_laundry;
> >+		return ret;
> >  	set_max_delegations();
> >  	return 0;
> >-
> >-out_free_laundry:
> >-	destroy_workqueue(laundry_wq);
> >-out:
> >-	return ret;
> >  }
> >  void
> >@@ -7850,7 +7840,6 @@ nfs4_state_shutdown_net(struct net *net)
> >  void
> >  nfs4_state_shutdown(void)
> >  {
> >-	destroy_workqueue(laundry_wq);
> >  	nfsd4_destroy_callback_queue();
> >  }
> >diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> >index 16920e4512bd..884e873b46ad 100644
> >--- a/fs/nfsd/nfsctl.c
> >+++ b/fs/nfsd/nfsctl.c
> >@@ -1544,6 +1544,11 @@ static int __init init_nfsd(void)
> >  	retval = register_cld_notifier();
> >  	if (retval)
> >  		goto out_free_all;
> >+	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
> >+	if (laundry_wq == NULL) {
> >+		retval = -ENOMEM;
> >+		goto out_free_all;
> >+	}
> >  	return 0;
> >  out_free_all:
> >  	unregister_pernet_subsys(&nfsd_net_ops);
> >@@ -1566,6 +1571,7 @@ static int __init init_nfsd(void)
> >  static void __exit exit_nfsd(void)
> >  {
> >+	destroy_workqueue(laundry_wq);
> >  	unregister_cld_notifier();
> >  	unregister_pernet_subsys(&nfsd_net_ops);
> >  	nfsd_drc_slab_free();
> >diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
> >index 23996c6ca75e..d41dcf1c4312 100644
> >--- a/fs/nfsd/nfsd.h
> >+++ b/fs/nfsd/nfsd.h
> >@@ -72,6 +72,7 @@ extern unsigned long		nfsd_drc_max_mem;
> >  extern unsigned long		nfsd_drc_mem_used;
> >  extern const struct seq_operations nfs_exports_op;
> >+extern struct workqueue_struct *laundry_wq;
> >  /*
> >   * Common void argument and result helpers
Dai Ngo April 25, 2022, 7:46 p.m. UTC | #3
On 4/25/22 12:35 PM, J. Bruce Fields wrote:
> On Mon, Apr 25, 2022 at 08:27:22AM -0700, dai.ngo@oracle.com wrote:
>> This patch has problem to build with this error:
>>
>>>> nfsctl.c:(.exit.text+0x0): undefined reference to `laundry_wq'
>>>> mipsel-linux-ld: nfsctl.c:(.exit.text+0x4): undefined reference to `laundry_wq'
>> This happens when CONFIG_NFSD is defined but CONFIG_NFSD_V4
>> is not. I think to fix this we need to also move the declaration
>> of laundry_wq from nfs4state.c to nfsctl.c. However this seems
>> odd since the laundry_wq is only used for v4, unless you have
>> any other suggestion.
> I'd just leave laundry_wq private to nfs4state.c.  Define
> create_laundromat() and destroy_laundromat() in nfs4state.c too.  And in
> nfsd.h, do the usual trick of defining no-op versions of those functions
> in the non-v4 case.  (See e.g. what we do with nfsd4_init/free_slabs().)

ok, thanks.

-Dai

>
> --b.
>
>> -Dai
>>
>> On 4/23/22 11:44 AM, Dai Ngo wrote:
>>> This patch moves create/destroy of laundry_wq from nfs4_state_start
>>> and nfs4_state_shutdown_net to init_nfsd and exit_nfsd to prevent
>>> the laundromat from being freed while a thread is processing a
>>> conflicting lock.
>>>
>>> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
>>> ---
>>>   fs/nfsd/nfs4state.c | 15 ++-------------
>>>   fs/nfsd/nfsctl.c    |  6 ++++++
>>>   fs/nfsd/nfsd.h      |  1 +
>>>   3 files changed, 9 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
>>> index b08c132648b9..b70ba2eb5665 100644
>>> --- a/fs/nfsd/nfs4state.c
>>> +++ b/fs/nfsd/nfs4state.c
>>> @@ -125,7 +125,7 @@ static void free_session(struct nfsd4_session *);
>>>   static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
>>>   static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
>>> -static struct workqueue_struct *laundry_wq;
>>> +struct workqueue_struct *laundry_wq;
>>>   static bool is_session_dead(struct nfsd4_session *ses)
>>>   {
>>> @@ -7798,22 +7798,12 @@ nfs4_state_start(void)
>>>   {
>>>   	int ret;
>>> -	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
>>> -	if (laundry_wq == NULL) {
>>> -		ret = -ENOMEM;
>>> -		goto out;
>>> -	}
>>>   	ret = nfsd4_create_callback_queue();
>>>   	if (ret)
>>> -		goto out_free_laundry;
>>> +		return ret;
>>>   	set_max_delegations();
>>>   	return 0;
>>> -
>>> -out_free_laundry:
>>> -	destroy_workqueue(laundry_wq);
>>> -out:
>>> -	return ret;
>>>   }
>>>   void
>>> @@ -7850,7 +7840,6 @@ nfs4_state_shutdown_net(struct net *net)
>>>   void
>>>   nfs4_state_shutdown(void)
>>>   {
>>> -	destroy_workqueue(laundry_wq);
>>>   	nfsd4_destroy_callback_queue();
>>>   }
>>> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
>>> index 16920e4512bd..884e873b46ad 100644
>>> --- a/fs/nfsd/nfsctl.c
>>> +++ b/fs/nfsd/nfsctl.c
>>> @@ -1544,6 +1544,11 @@ static int __init init_nfsd(void)
>>>   	retval = register_cld_notifier();
>>>   	if (retval)
>>>   		goto out_free_all;
>>> +	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
>>> +	if (laundry_wq == NULL) {
>>> +		retval = -ENOMEM;
>>> +		goto out_free_all;
>>> +	}
>>>   	return 0;
>>>   out_free_all:
>>>   	unregister_pernet_subsys(&nfsd_net_ops);
>>> @@ -1566,6 +1571,7 @@ static int __init init_nfsd(void)
>>>   static void __exit exit_nfsd(void)
>>>   {
>>> +	destroy_workqueue(laundry_wq);
>>>   	unregister_cld_notifier();
>>>   	unregister_pernet_subsys(&nfsd_net_ops);
>>>   	nfsd_drc_slab_free();
>>> diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
>>> index 23996c6ca75e..d41dcf1c4312 100644
>>> --- a/fs/nfsd/nfsd.h
>>> +++ b/fs/nfsd/nfsd.h
>>> @@ -72,6 +72,7 @@ extern unsigned long		nfsd_drc_max_mem;
>>>   extern unsigned long		nfsd_drc_mem_used;
>>>   extern const struct seq_operations nfs_exports_op;
>>> +extern struct workqueue_struct *laundry_wq;
>>>   /*
>>>    * Common void argument and result helpers
diff mbox series

Patch

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b08c132648b9..b70ba2eb5665 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -125,7 +125,7 @@  static void free_session(struct nfsd4_session *);
 static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
 static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
 
-static struct workqueue_struct *laundry_wq;
+struct workqueue_struct *laundry_wq;
 
 static bool is_session_dead(struct nfsd4_session *ses)
 {
@@ -7798,22 +7798,12 @@  nfs4_state_start(void)
 {
 	int ret;
 
-	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
-	if (laundry_wq == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
 	ret = nfsd4_create_callback_queue();
 	if (ret)
-		goto out_free_laundry;
+		return ret;
 
 	set_max_delegations();
 	return 0;
-
-out_free_laundry:
-	destroy_workqueue(laundry_wq);
-out:
-	return ret;
 }
 
 void
@@ -7850,7 +7840,6 @@  nfs4_state_shutdown_net(struct net *net)
 void
 nfs4_state_shutdown(void)
 {
-	destroy_workqueue(laundry_wq);
 	nfsd4_destroy_callback_queue();
 }
 
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 16920e4512bd..884e873b46ad 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1544,6 +1544,11 @@  static int __init init_nfsd(void)
 	retval = register_cld_notifier();
 	if (retval)
 		goto out_free_all;
+	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
+	if (laundry_wq == NULL) {
+		retval = -ENOMEM;
+		goto out_free_all;
+	}
 	return 0;
 out_free_all:
 	unregister_pernet_subsys(&nfsd_net_ops);
@@ -1566,6 +1571,7 @@  static int __init init_nfsd(void)
 
 static void __exit exit_nfsd(void)
 {
+	destroy_workqueue(laundry_wq);
 	unregister_cld_notifier();
 	unregister_pernet_subsys(&nfsd_net_ops);
 	nfsd_drc_slab_free();
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 23996c6ca75e..d41dcf1c4312 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -72,6 +72,7 @@  extern unsigned long		nfsd_drc_max_mem;
 extern unsigned long		nfsd_drc_mem_used;
 
 extern const struct seq_operations nfs_exports_op;
+extern struct workqueue_struct *laundry_wq;
 
 /*
  * Common void argument and result helpers