linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ceph: Fix log output race condition in osd client
@ 2025-09-23 11:08 Simon Buttgereit
  2025-09-23 17:27 ` Viacheslav Dubeyko
  0 siblings, 1 reply; 4+ messages in thread
From: Simon Buttgereit @ 2025-09-23 11:08 UTC (permalink / raw)
  To: ceph-devel; +Cc: linux-fsdevel, idryomov, xiubli, Simon Buttgereit

OSD client logging has a problem in get_osd() and put_osd().
For one logging output refcount_read() is called twice. If recount
value changes between both calls logging output is not consistent.

This patch adds an additional variable to store the current refcount
before using it in the logging macro.

Signed-off-by: Simon Buttgereit <simon.buttgereit@tu-ilmenau.de>
---
 net/ceph/osd_client.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 6664ea73ccf8..b8d20ab1976e 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1280,8 +1280,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
 static struct ceph_osd *get_osd(struct ceph_osd *osd)
 {
 	if (refcount_inc_not_zero(&osd->o_ref)) {
-		dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
-		     refcount_read(&osd->o_ref));
+		unsigned int refcount = refcount_read(&osd->o_ref);
+
+		dout("get_osd %p %d -> %d\n", osd, refcount - 1, refcount);
 		return osd;
 	} else {
 		dout("get_osd %p FAIL\n", osd);
@@ -1291,8 +1292,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
 
 static void put_osd(struct ceph_osd *osd)
 {
-	dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
-	     refcount_read(&osd->o_ref) - 1);
+	unsigned int refcount = refcount_read(&osd->o_ref);
+
+	dout("put_osd %p %d -> %d\n", osd, refcount, refcount - 1);
 	if (refcount_dec_and_test(&osd->o_ref)) {
 		osd_cleanup(osd);
 		kfree(osd);
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re:  [PATCH] ceph: Fix log output race condition in osd client
  2025-09-23 11:08 [PATCH] ceph: Fix log output race condition in osd client Simon Buttgereit
@ 2025-09-23 17:27 ` Viacheslav Dubeyko
  2025-09-24 13:57   ` Simon Buttgereit
  0 siblings, 1 reply; 4+ messages in thread
From: Viacheslav Dubeyko @ 2025-09-23 17:27 UTC (permalink / raw)
  To: ceph-devel@vger.kernel.org, simon.buttgereit@tu-ilmenau.de
  Cc: idryomov@gmail.com, linux-fsdevel@vger.kernel.org, Xiubo Li

On Tue, 2025-09-23 at 13:08 +0200, Simon Buttgereit wrote:
> OSD client logging has a problem in get_osd() and put_osd().
> For one logging output refcount_read() is called twice. If recount
> value changes between both calls logging output is not consistent.
> 
> This patch adds an additional variable to store the current refcount
> before using it in the logging macro.
> 
> Signed-off-by: Simon Buttgereit <simon.buttgereit@tu-ilmenau.de>
> ---
>  net/ceph/osd_client.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> index 6664ea73ccf8..b8d20ab1976e 100644
> --- a/net/ceph/osd_client.c
> +++ b/net/ceph/osd_client.c
> @@ -1280,8 +1280,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
>  static struct ceph_osd *get_osd(struct ceph_osd *osd)
>  {
>  	if (refcount_inc_not_zero(&osd->o_ref)) {
> -		dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
> -		     refcount_read(&osd->o_ref));
> +		unsigned int refcount = refcount_read(&osd->o_ref);
> +
> +		dout("get_osd %p %d -> %d\n", osd, refcount - 1, refcount);

Frankly speaking, I don't see the point in this change. First of all, it's the
debug output and to be really precise could be not necessary here. And it is
easy to make correct conclusion from the debug output about real value of
refcount, even if value changes between both calls. Secondly, more important,
currently we have  refcount_read() as part of dout() call. After this change,
the refcount_read() will be called and assigned to refcount value, even if we
don't need in debug output.

Are you sure that you can compile the driver without warnings if
CONFIG_DYNAMIC_DEBUG=n?

Thanks,
Slava.

>  		return osd;
>  	} else {
>  		dout("get_osd %p FAIL\n", osd);
> @@ -1291,8 +1292,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
>  
>  static void put_osd(struct ceph_osd *osd)
>  {
> -	dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
> -	     refcount_read(&osd->o_ref) - 1);
> +	unsigned int refcount = refcount_read(&osd->o_ref);
> +
> +	dout("put_osd %p %d -> %d\n", osd, refcount, refcount - 1);
>  	if (refcount_dec_and_test(&osd->o_ref)) {
>  		osd_cleanup(osd);
>  		kfree(osd);

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re:  [PATCH] ceph: Fix log output race condition in osd client
  2025-09-23 17:27 ` Viacheslav Dubeyko
@ 2025-09-24 13:57   ` Simon Buttgereit
  2025-09-24 17:55     ` Viacheslav Dubeyko
  0 siblings, 1 reply; 4+ messages in thread
From: Simon Buttgereit @ 2025-09-24 13:57 UTC (permalink / raw)
  To: Viacheslav Dubeyko
  Cc: idryomov@gmail.com, linux-fsdevel@vger.kernel.org, Xiubo Li

On Tue, 2025-09-23 at 17:27 +0000, Viacheslav Dubeyko wrote:
> On Tue, 2025-09-23 at 13:08 +0200, Simon Buttgereit wrote:
> > OSD client logging has a problem in get_osd() and put_osd().
> > For one logging output refcount_read() is called twice. If recount
> > value changes between both calls logging output is not consistent.
> > 
> > This patch adds an additional variable to store the current
> > refcount
> > before using it in the logging macro.
> > 
> > Signed-off-by: Simon Buttgereit <simon.buttgereit@tu-ilmenau.de>
> > ---
> >  net/ceph/osd_client.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> > index 6664ea73ccf8..b8d20ab1976e 100644
> > --- a/net/ceph/osd_client.c
> > +++ b/net/ceph/osd_client.c
> > @@ -1280,8 +1280,9 @@ static struct ceph_osd *create_osd(struct
> > ceph_osd_client *osdc, int onum)
> >  static struct ceph_osd *get_osd(struct ceph_osd *osd)
> >  {
> >  	if (refcount_inc_not_zero(&osd->o_ref)) {
> > -		dout("get_osd %p %d -> %d\n", osd,
> > refcount_read(&osd->o_ref)-1,
> > -		     refcount_read(&osd->o_ref));
> > +		unsigned int refcount = refcount_read(&osd-
> > >o_ref);
> > +
> > +		dout("get_osd %p %d -> %d\n", osd, refcount - 1,
> > refcount);
> 
> Frankly speaking, I don't see the point in this change. First of all,
> it's the
> debug output and to be really precise could be not necessary here.
> And it is
> easy to make correct conclusion from the debug output about real
> value of
> refcount, even if value changes between both calls. Secondly, more
> important,
> currently we have  refcount_read() as part of dout() call. After this
> change,
> the refcount_read() will be called and assigned to refcount value,
> even if we
> don't need in debug output.
> 
> Are you sure that you can compile the driver without warnings if
> CONFIG_DYNAMIC_DEBUG=n?
> 
> Thanks,
> Slava.
> 
> >  		return osd;
> >  	} else {
> >  		dout("get_osd %p FAIL\n", osd);
> > @@ -1291,8 +1292,9 @@ static struct ceph_osd *get_osd(struct
> > ceph_osd *osd)
> >  
> >  static void put_osd(struct ceph_osd *osd)
> >  {
> > -	dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd-
> > >o_ref),
> > -	     refcount_read(&osd->o_ref) - 1);
> > +	unsigned int refcount = refcount_read(&osd->o_ref);
> > +
> > +	dout("put_osd %p %d -> %d\n", osd, refcount, refcount -
> > 1);
> >  	if (refcount_dec_and_test(&osd->o_ref)) {
> >  		osd_cleanup(osd);
> >  		kfree(osd);

Hi Slava,
thank you for your quick answer.

I checked it again: I built the kernel with gcc 15.2.1 with -Werror and
CONFIG_DYNAMIC_DEBUG=n and everything ran through fine without any
errors.
I guess because of the way no_printk(fmt, ...) is built.

And for sure, this is only debug output, but right now, there is a race
condition, which I went into, and in my opinion this should be fixed.
Another option, which would be completely fine for me, could be to
remove one recount_read call. This would result in something like:

dout("get_osd %p; new refcount = %d\n", osd, refcount_read(&osd-
>o_ref));

If you have another idea on how to handle this I'm open to your
suggestions.

Best Regards
Simon

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE:  [PATCH] ceph: Fix log output race condition in osd client
  2025-09-24 13:57   ` Simon Buttgereit
@ 2025-09-24 17:55     ` Viacheslav Dubeyko
  0 siblings, 0 replies; 4+ messages in thread
From: Viacheslav Dubeyko @ 2025-09-24 17:55 UTC (permalink / raw)
  To: simon.buttgereit@tu-ilmenau.de
  Cc: idryomov@gmail.com, linux-fsdevel@vger.kernel.org,
	Pavan Rallabhandi, Xiubo Li

On Wed, 2025-09-24 at 15:57 +0200, Simon Buttgereit wrote:
> On Tue, 2025-09-23 at 17:27 +0000, Viacheslav Dubeyko wrote:
> > On Tue, 2025-09-23 at 13:08 +0200, Simon Buttgereit wrote:
> > > OSD client logging has a problem in get_osd() and put_osd().
> > > For one logging output refcount_read() is called twice. If recount
> > > value changes between both calls logging output is not consistent.
> > > 
> > > This patch adds an additional variable to store the current
> > > refcount
> > > before using it in the logging macro.
> > > 
> > > Signed-off-by: Simon Buttgereit <simon.buttgereit@tu-ilmenau.de>
> > > ---
> > >  net/ceph/osd_client.c | 10 ++++++----
> > >  1 file changed, 6 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> > > index 6664ea73ccf8..b8d20ab1976e 100644
> > > --- a/net/ceph/osd_client.c
> > > +++ b/net/ceph/osd_client.c
> > > @@ -1280,8 +1280,9 @@ static struct ceph_osd *create_osd(struct
> > > ceph_osd_client *osdc, int onum)
> > >  static struct ceph_osd *get_osd(struct ceph_osd *osd)
> > >  {
> > >  	if (refcount_inc_not_zero(&osd->o_ref)) {
> > > -		dout("get_osd %p %d -> %d\n", osd,
> > > refcount_read(&osd->o_ref)-1,
> > > -		     refcount_read(&osd->o_ref));
> > > +		unsigned int refcount = refcount_read(&osd-
> > > > o_ref);
> > > +
> > > +		dout("get_osd %p %d -> %d\n", osd, refcount - 1,
> > > refcount);
> > 
> > Frankly speaking, I don't see the point in this change. First of all,
> > it's the
> > debug output and to be really precise could be not necessary here.
> > And it is
> > easy to make correct conclusion from the debug output about real
> > value of
> > refcount, even if value changes between both calls. Secondly, more
> > important,
> > currently we have  refcount_read() as part of dout() call. After this
> > change,
> > the refcount_read() will be called and assigned to refcount value,
> > even if we
> > don't need in debug output.
> > 
> > Are you sure that you can compile the driver without warnings if
> > CONFIG_DYNAMIC_DEBUG=n?
> > 
> > Thanks,
> > Slava.
> > 
> > >  		return osd;
> > >  	} else {
> > >  		dout("get_osd %p FAIL\n", osd);
> > > @@ -1291,8 +1292,9 @@ static struct ceph_osd *get_osd(struct
> > > ceph_osd *osd)
> > >  
> > >  static void put_osd(struct ceph_osd *osd)
> > >  {
> > > -	dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd-
> > > > o_ref),
> > > -	     refcount_read(&osd->o_ref) - 1);
> > > +	unsigned int refcount = refcount_read(&osd->o_ref);
> > > +
> > > +	dout("put_osd %p %d -> %d\n", osd, refcount, refcount -
> > > 1);
> > >  	if (refcount_dec_and_test(&osd->o_ref)) {
> > >  		osd_cleanup(osd);
> > >  		kfree(osd);
> 
> Hi Slava,
> thank you for your quick answer.
> 
> I checked it again: I built the kernel with gcc 15.2.1 with -Werror and
> CONFIG_DYNAMIC_DEBUG=n and everything ran through fine without any
> errors.
> I guess because of the way no_printk(fmt, ...) is built.
> 
> And for sure, this is only debug output, but right now, there is a race
> condition, which I went into, and in my opinion this should be fixed.
> Another option, which would be completely fine for me, could be to
> remove one recount_read call. This would result in something like:
> 
> dout("get_osd %p; new refcount = %d\n", osd, refcount_read(&osd-
> > o_ref));
> 
> If you have another idea on how to handle this I'm open to your
> suggestions.
> 

Hi Simon,

I think that removing one refcount_read() call looks like more clean solution.
Likewise statement:

dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
refcount_read(&osd->o_ref) - 1);

smells really bad for my taste and it looks like the overkill anyway. :)

Thanks,
Slava.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-09-24 17:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23 11:08 [PATCH] ceph: Fix log output race condition in osd client Simon Buttgereit
2025-09-23 17:27 ` Viacheslav Dubeyko
2025-09-24 13:57   ` Simon Buttgereit
2025-09-24 17:55     ` Viacheslav Dubeyko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).