[PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk

Sean Chang posted 2 patches 5 days, 16 hours ago
[PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Sean Chang 5 days, 16 hours ago
When CONFIG_SUNRPC_DEBUG is disabled, the dfprintk() macros currently
expand to empty do-while loops. This causes variables used solely
within these calls to appear unused, triggering -Wunused-variable
warnings.

Instead of marking every affected variable with __maybe_unused,
update the dfprintk and dfprintk_rcu stubs to use no_printk().
This allows the compiler to see the variables and perform type
checking without emitting any code, thus silencing the warnings
globally for these macros.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Sean Chang <seanwascoding@gmail.com>
---
 include/linux/sunrpc/debug.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index eb4bd62df319..55c54df8bc7d 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -52,8 +52,8 @@ do {									\
 # define RPC_IFDEBUG(x)		x
 #else
 # define ifdebug(fac)		if (0)
-# define dfprintk(fac, fmt, ...)	do {} while (0)
-# define dfprintk_rcu(fac, fmt, ...)	do {} while (0)
+# define dfprintk(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
+# define dfprintk_rcu(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
 # define RPC_IFDEBUG(x)
 #endif
 
-- 
2.34.1
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by David Laight 5 days, 14 hours ago
On Fri, 27 Feb 2026 23:26:23 +0800
Sean Chang <seanwascoding@gmail.com> wrote:

> When CONFIG_SUNRPC_DEBUG is disabled, the dfprintk() macros currently
> expand to empty do-while loops. This causes variables used solely
> within these calls to appear unused, triggering -Wunused-variable
> warnings.
> 
> Instead of marking every affected variable with __maybe_unused,
> update the dfprintk and dfprintk_rcu stubs to use no_printk().
> This allows the compiler to see the variables and perform type
> checking without emitting any code, thus silencing the warnings
> globally for these macros.
> 
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Sean Chang <seanwascoding@gmail.com>
> ---
>  include/linux/sunrpc/debug.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> index eb4bd62df319..55c54df8bc7d 100644
> --- a/include/linux/sunrpc/debug.h
> +++ b/include/linux/sunrpc/debug.h
> @@ -52,8 +52,8 @@ do {									\
>  # define RPC_IFDEBUG(x)		x
>  #else
>  # define ifdebug(fac)		if (0)
> -# define dfprintk(fac, fmt, ...)	do {} while (0)
> -# define dfprintk_rcu(fac, fmt, ...)	do {} while (0)
> +# define dfprintk(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
> +# define dfprintk_rcu(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)

You can omit fmt, then you don't need the ##
#define dfprintk(fac, ...)	no_printk(__VA_ARGS__)

	David

>  # define RPC_IFDEBUG(x)
>  #endif
>
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Andrew Lunn 5 days, 14 hours ago
> >  # define ifdebug(fac)		if (0)
> > -# define dfprintk(fac, fmt, ...)	do {} while (0)
> > -# define dfprintk_rcu(fac, fmt, ...)	do {} while (0)
> > +# define dfprintk(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
> > +# define dfprintk_rcu(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
> 
> You can omit fmt, then you don't need the ##
> #define dfprintk(fac, ...)	no_printk(__VA_ARGS__)

/*
 * Dummy printk for disabled debugging statements to use whilst maintaining
 * gcc's format checking.
 */
#define no_printk(fmt, ...)				\
({							\
	if (0)						\
		_printk(fmt, ##__VA_ARGS__);		\
	0;						\
})

Without fmt, gcc cannot do format checking. Or worse, it takes the
first member of __VA_ARGS__ as the format, and gives spurious errors?

      Andrew
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by David Laight 5 days, 13 hours ago
On Fri, 27 Feb 2026 18:57:33 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

> > >  # define ifdebug(fac)		if (0)
> > > -# define dfprintk(fac, fmt, ...)	do {} while (0)
> > > -# define dfprintk_rcu(fac, fmt, ...)	do {} while (0)
> > > +# define dfprintk(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
> > > +# define dfprintk_rcu(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)  
> > 
> > You can omit fmt, then you don't need the ##
> > #define dfprintk(fac, ...)	no_printk(__VA_ARGS__)  
> 
> /*
>  * Dummy printk for disabled debugging statements to use whilst maintaining
>  * gcc's format checking.
>  */
> #define no_printk(fmt, ...)				\
> ({							\
> 	if (0)						\
> 		_printk(fmt, ##__VA_ARGS__);		\
> 	0;						\
> })
> 
> Without fmt, gcc cannot do format checking. Or worse, it takes the
> first member of __VA_ARGS__ as the format, and gives spurious errors?

By the time the compiler looks at it the pre-processor has expanded
__VA_ARGS__.
So it doesn't matter that the format string is in the __VA_ARGS__
list rather than preceding it.

	David 

> 
>       Andrew
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Sean Chang 4 days, 17 hours ago
On Sat, Feb 28, 2026 at 2:15 AM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Fri, 27 Feb 2026 18:57:33 +0100
> Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > >  # define ifdebug(fac)            if (0)
> > > > -# define dfprintk(fac, fmt, ...) do {} while (0)
> > > > -# define dfprintk_rcu(fac, fmt, ...)     do {} while (0)
> > > > +# define dfprintk(fac, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
> > > > +# define dfprintk_rcu(fac, fmt, ...)     no_printk(fmt, ##__VA_ARGS__)
> > >
> > > You can omit fmt, then you don't need the ##
> > > #define dfprintk(fac, ...)  no_printk(__VA_ARGS__)
> >
> > /*
> >  * Dummy printk for disabled debugging statements to use whilst maintaining
> >  * gcc's format checking.
> >  */
> > #define no_printk(fmt, ...)                           \
> > ({                                                    \
> >       if (0)                                          \
> >               _printk(fmt, ##__VA_ARGS__);            \
> >       0;                                              \
> > })
> >
> > Without fmt, gcc cannot do format checking. Or worse, it takes the
> > first member of __VA_ARGS__ as the format, and gives spurious errors?
>
> By the time the compiler looks at it the pre-processor has expanded
> __VA_ARGS__.
> So it doesn't matter that the format string is in the __VA_ARGS__
> list rather than preceding it.
>

Hi David,
Thanks for the explanation. I agree that since __VA_ARGS__ will
always contain the format string in this context, the ## and explicit
fmt are indeed redundant. Since no_printk itself already handles
the ##__VA_ARGS__ logic internally, there's no need to duplicate
it in the dfprintk definition.

I'll switch to the simpler in v5:
-# define dfprintk(fac, fmt, ...)            no_printk(fmt, ##__VA_ARGS__)
-# define dfprintk_rcu(fac, fmt, ...)     no_printk(fmt, ##__VA_ARGS__)
+#define dfprintk(fac, ...)                   no_printk(__VA_ARGS__)
+# define dfprintk_rcu(fac, ...)           no_printk(__VA_ARGS__)

Best regards,
Sean
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Sean Chang 4 days, 14 hours ago
On Sat, Feb 28, 2026 at 10:56 PM Sean Chang <seanwascoding@gmail.com> wrote:
>
> On Sat, Feb 28, 2026 at 2:15 AM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Fri, 27 Feb 2026 18:57:33 +0100
> > Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > > > >  # define ifdebug(fac)            if (0)
> > > > > -# define dfprintk(fac, fmt, ...) do {} while (0)
> > > > > -# define dfprintk_rcu(fac, fmt, ...)     do {} while (0)
> > > > > +# define dfprintk(fac, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
> > > > > +# define dfprintk_rcu(fac, fmt, ...)     no_printk(fmt, ##__VA_ARGS__)
> > > >
> > > > You can omit fmt, then you don't need the ##
> > > > #define dfprintk(fac, ...)  no_printk(__VA_ARGS__)
> > >
> > > /*
> > >  * Dummy printk for disabled debugging statements to use whilst maintaining
> > >  * gcc's format checking.
> > >  */
> > > #define no_printk(fmt, ...)                           \
> > > ({                                                    \
> > >       if (0)                                          \
> > >               _printk(fmt, ##__VA_ARGS__);            \
> > >       0;                                              \
> > > })
> > >
> > > Without fmt, gcc cannot do format checking. Or worse, it takes the
> > > first member of __VA_ARGS__ as the format, and gives spurious errors?
> >
> > By the time the compiler looks at it the pre-processor has expanded
> > __VA_ARGS__.
> > So it doesn't matter that the format string is in the __VA_ARGS__
> > list rather than preceding it.
> >
>
> Hi David,
> Thanks for the explanation. I agree that since __VA_ARGS__ will
> always contain the format string in this context, the ## and explicit
> fmt are indeed redundant. Since no_printk itself already handles
> the ##__VA_ARGS__ logic internally, there's no need to duplicate
> it in the dfprintk definition.
>
> I'll switch to the simpler in v5:
> -# define dfprintk(fac, fmt, ...)            no_printk(fmt, ##__VA_ARGS__)
> -# define dfprintk_rcu(fac, fmt, ...)     no_printk(fmt, ##__VA_ARGS__)
> +#define dfprintk(fac, ...)                   no_printk(__VA_ARGS__)
> +# define dfprintk_rcu(fac, ...)           no_printk(__VA_ARGS__)
>

HI all,
I've also identified the cause of the build error in fs/nfsd/nfsfh.c
reported by syzbot [1]. The "use of undeclared identifier 'buf'" occurs
because buf is only declared within the RPC_IFDEBUG macro,
which is removed when CONFIG_SUNRPC_DEBUG is disabled.
To fix this, I will follow the pattern used in net/sunrpc/xprtrdma/
svc_rdma_transport.c by wrapping the dprintk call that references
buf within an #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) block.

static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
{
....
RPC_IFDEBUG(struct sockaddr *sap);
...
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
dprintk("svcrdma: new connection accepted on device %s:\n", dev->name);
sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
dprintk(" local address : %pIS:%u\n", sap, rpc_get_port(sap));
sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
dprintk(" remote address : %pIS:%u\n", sap, rpc_get_port(sap));
dprintk(" max_sge : %d\n", newxprt->sc_max_send_sges);
dprintk(" sq_depth : %d\n", newxprt->sc_sq_depth);
dprintk(" rdma_rw_ctxs : %d\n", ctxts);
dprintk(" max_requests : %d\n", newxprt->sc_max_requests);
dprintk(" ord : %d\n", conn_param.initiator_depth);
#endif
...
}

The refactor in fs/nfsd/nfsfh.c will look like this:

static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
struct svc_cred *cred,
struct svc_export *exp)
{
    /* Check if the request originated from a secure port. */
    if (rqstp && !nfsd_originating_port_ok(rqstp, cred, exp)) {
       RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
       dprintk("nfsd: request from insecure port %s!\n",
       svc_print_addr(rqstp, buf, sizeof(buf)));
+#endif
       return nfserr_perm;
    }

    /* Set user creds for this exportpoint */
    return nfserrno(nfsd_setuser(cred, exp));
}

This fix, along with the macro simplification suggested by David, will
be included in v5.

[1] https://lore.kernel.org/all/69a2e269.050a0220.3a55be.003e.GAE@google.com/

Best regards,
Sean
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Andrew Lunn 4 days, 12 hours ago
> HI all,
> I've also identified the cause of the build error in fs/nfsd/nfsfh.c
> reported by syzbot [1]. The "use of undeclared identifier 'buf'" occurs
> because buf is only declared within the RPC_IFDEBUG macro,
> which is removed when CONFIG_SUNRPC_DEBUG is disabled.
> To fix this, I will follow the pattern used in net/sunrpc/xprtrdma/
> svc_rdma_transport.c by wrapping the dprintk call that references
> buf within an #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) block.

Please try to avoid adding such #if code. Compile testing does not
work as well if there are millions of #if def combinations. Ideally we
want the stub functions to allow as much as possible to be compiled,
and then let the optimizer throw it out because it is unreachable.

> 
> static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
> {
> ....
> RPC_IFDEBUG(struct sockaddr *sap);
> ...
> #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
> dprintk("svcrdma: new connection accepted on device %s:\n", dev->name);
> sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
> dprintk(" local address : %pIS:%u\n", sap, rpc_get_port(sap));
> sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
> dprintk(" remote address : %pIS:%u\n", sap, rpc_get_port(sap));
> dprintk(" max_sge : %d\n", newxprt->sc_max_send_sges);
> dprintk(" sq_depth : %d\n", newxprt->sc_sq_depth);
> dprintk(" rdma_rw_ctxs : %d\n", ctxts);
> dprintk(" max_requests : %d\n", newxprt->sc_max_requests);
> dprintk(" ord : %d\n", conn_param.initiator_depth);
> #endif
> ...
> }
> 
> The refactor in fs/nfsd/nfsfh.c will look like this:
> 
> static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
> struct svc_cred *cred,
> struct svc_export *exp)
> {
>     /* Check if the request originated from a secure port. */
>     if (rqstp && !nfsd_originating_port_ok(rqstp, cred, exp)) {
>        RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
> +#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
>        dprintk("nfsd: request from insecure port %s!\n",
>        svc_print_addr(rqstp, buf, sizeof(buf)));
> +#endif

In this case, now dprintk() uses it arguments, i think you can drop
the RPC_IFDEBUG() and always have buf. This code then gets
compiled. Ask make to produce fs/nfsd/nfsfh.lst and see if it
generated any code for this, or has it optimized it out.

	  Andrew
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Sean Chang 3 days, 16 hours ago
On Sun, Mar 1, 2026 at 4:04 AM Andrew Lunn <andrew@lunn.ch> wrote:
>
> Please try to avoid adding such #if code. Compile testing does not
> work as well if there are millions of #if def combinations. Ideally we
> want the stub functions to allow as much as possible to be compiled,
> and then let the optimizer throw it out because it is unreachable.
>
> >
> > static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
> > {
> > ....
> > RPC_IFDEBUG(struct sockaddr *sap);
> > ...
> > #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
> > dprintk("svcrdma: new connection accepted on device %s:\n", dev->name);
> > sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
> > dprintk(" local address : %pIS:%u\n", sap, rpc_get_port(sap));
> > sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
> > dprintk(" remote address : %pIS:%u\n", sap, rpc_get_port(sap));
> > dprintk(" max_sge : %d\n", newxprt->sc_max_send_sges);
> > dprintk(" sq_depth : %d\n", newxprt->sc_sq_depth);
> > dprintk(" rdma_rw_ctxs : %d\n", ctxts);
> > dprintk(" max_requests : %d\n", newxprt->sc_max_requests);
> > dprintk(" ord : %d\n", conn_param.initiator_depth);
> > #endif
> > ...
> > }
> >
> > The refactor in fs/nfsd/nfsfh.c will look like this:
> >
> > static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
> > struct svc_cred *cred,
> > struct svc_export *exp)
> > {
> >     /* Check if the request originated from a secure port. */
> >     if (rqstp && !nfsd_originating_port_ok(rqstp, cred, exp)) {
> >        RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
> > +#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
> >        dprintk("nfsd: request from insecure port %s!\n",
> >        svc_print_addr(rqstp, buf, sizeof(buf)));
> > +#endif
>
> In this case, now dprintk() uses it arguments, i think you can drop
> the RPC_IFDEBUG() and always have buf. This code then gets
> compiled. Ask make to produce fs/nfsd/nfsfh.lst and see if it
> generated any code for this, or has it optimized it out.
>

Hi Andrew,
You are absolutely right. I have verified the generated code with
fs/nfsd/nfsfh.lst and net/sunrpc/xprtrdma/svc_rdma_transport.lst
under -O2 optimization.

Even after dropping the #ifdef and always declaring the char buf[],
the compiler successfully optimizes everything out when
CONFIG_SUNRPC_DEBUG is disabled. Specifically:
- There is no stack allocation (no sub %rsp) for the buffer.
- The logic flows directly as if the dprintk lines were never there.

Given this, I agree it is the perfect time to also remove the
RPC_IFDEBUG(x) macro entirely, as it is only used in these
two files and is now redundant with the new no_printk approach.

I will send out v6 shortly with these cleanups.

Best Regards,
Sean
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Andrew Lunn 5 days, 16 hours ago
On Fri, Feb 27, 2026 at 11:26:23PM +0800, Sean Chang wrote:
> When CONFIG_SUNRPC_DEBUG is disabled, the dfprintk() macros currently
> expand to empty do-while loops. This causes variables used solely
> within these calls to appear unused, triggering -Wunused-variable
> warnings.
> 
> Instead of marking every affected variable with __maybe_unused,
> update the dfprintk and dfprintk_rcu stubs to use no_printk().
> This allows the compiler to see the variables and perform type
> checking without emitting any code, thus silencing the warnings
> globally for these macros.
> 
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Sean Chang <seanwascoding@gmail.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew
Re: [PATCH v4 1/2] sunrpc: fix unused variable warnings by using no_printk
Posted by Chuck Lever 5 days, 16 hours ago

On Fri, Feb 27, 2026, at 10:26 AM, Sean Chang wrote:
> When CONFIG_SUNRPC_DEBUG is disabled, the dfprintk() macros currently
> expand to empty do-while loops. This causes variables used solely
> within these calls to appear unused, triggering -Wunused-variable
> warnings.
>
> Instead of marking every affected variable with __maybe_unused,
> update the dfprintk and dfprintk_rcu stubs to use no_printk().
> This allows the compiler to see the variables and perform type
> checking without emitting any code, thus silencing the warnings
> globally for these macros.
>
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Sean Chang <seanwascoding@gmail.com>
> ---
>  include/linux/sunrpc/debug.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> index eb4bd62df319..55c54df8bc7d 100644
> --- a/include/linux/sunrpc/debug.h
> +++ b/include/linux/sunrpc/debug.h
> @@ -52,8 +52,8 @@ do {									\
>  # define RPC_IFDEBUG(x)		x
>  #else
>  # define ifdebug(fac)		if (0)
> -# define dfprintk(fac, fmt, ...)	do {} while (0)
> -# define dfprintk_rcu(fac, fmt, ...)	do {} while (0)
> +# define dfprintk(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
> +# define dfprintk_rcu(fac, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
>  # define RPC_IFDEBUG(x)
>  #endif
> 
> -- 
> 2.34.1

Seems obviously good to me.

Reviewed-by: Chuck Lever <chuck.lever@oracle.com>


-- 
Chuck Lever