All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ira Weiny <ira.weiny@intel.com>
To: Bjorn Helgaas <helgaas@kernel.org>
Cc: Lukas Wunner <lukas@wunner.de>,
	Dan Williams <dan.j.williams@intel.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Gregory Price <gregory.price@memverge.com>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Alison Schofield <alison.schofield@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	Ben Widawsky <bwidawsk@kernel.org>, <linux-cxl@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <linux-pci@vger.kernel.org>
Subject: Re: [PATCH] PCI/doe: Fix work struct declaration
Date: Wed, 16 Nov 2022 12:57:55 -0800	[thread overview]
Message-ID: <Y3VO07WbMI5EYAUD@iweiny-mobl> (raw)
In-Reply-To: <20221116182037.GA1127308@bhelgaas>

On Wed, Nov 16, 2022 at 12:20:37PM -0600, Bjorn Helgaas wrote:
> On Wed, Nov 16, 2022 at 11:09:39AM +0100, Lukas Wunner wrote:
> > On Mon, Nov 14, 2022 at 05:19:43PM -0800, ira.weiny@intel.com wrote:
> > > From: Ira Weiny <ira.weiny@intel.com>
> > > 
> > > The callers of pci_doe_submit_task() allocate the pci_doe_task on the
> > > stack.  This causes the work structure to be allocated on the stack
> > > without pci_doe_submit_task() knowing.  Work item initialization needs
> > > to be done with either INIT_WORK_ONSTACK() or INIT_WORK() depending on
> > > how the work item is allocated.
> > > 
> > > Jonathan suggested creating doe task allocation macros such as
> > > DECLARE_CDAT_DOE_TASK_ONSTACK().[1]  The issue with this is the work
> > > function is not known to the callers and must be initialized correctly.
> > > 
> > > A follow up suggestion was to have an internal 'pci_doe_work' item
> > > allocated by pci_doe_submit_task().[2]  This requires an allocation which
> > > could restrict the context where tasks are used.
> > > 
> > > Compromise with an intermediate step to initialize the task struct with
> > > a new call pci_doe_init_task() which must be called prior to submit
> > > task.
> > > 
> > > [1] https://lore.kernel.org/linux-cxl/20221014151045.24781-1-Jonathan.Cameron@huawei.com/T/#m88a7f50dcce52f30c8bf5c3dcc06fa9843b54a2d
> > > [2] https://lore.kernel.org/linux-cxl/20221014151045.24781-1-Jonathan.Cameron@huawei.com/T/#m63c636c5135f304480370924f4d03c00357be667
> > 
> > We have object_is_on_stack(), included from <linux/sched/task_stack.h>.
> > 
> > So you could just autosense in pci_doe_submit_task() whether
> > pci_doe_task is on the stack and call the appropriate INIT_WORK
> > variant.
> 
> Nifty, I had no idea object_is_on_stack() existed, thank you!

Indeed!  Neither did I!  thanks!

> 
> I wonder if there's an opportunity to use object_is_on_stack()
> somewhere in the INIT_WORK() path to find usage mistakes.

I'm thinking we could make INIT_WORK do the right thing all the time.  Not sure
what the overhead of object_is_on_stack() is.

> 
> Adding it in pci_doe_submit_task() would add some complexity, so I'm
> not sure whether it's worth adding it unless we actually have uses for
> both cases.

I think if we don't do something we have to document that
pci_doe_submit_task() only works with tasks on the stack.

I would rather just make pci_doe_submit_task() correct and not complicate the
callers.  object_is_on_stack() can't be enough overhead to be worried about in
this call path can it?

Actually after writing all that I wonder if we can't push the use of
object_is_on_stack() into the debug code?  Something like below (completely
untested)?  I think this could be pushed even further down but I'd like to get
opinions before attempting a change which will have a wider blast radius.

Ira


diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index a0143dd24430..4cc50b554a29 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -199,7 +199,7 @@ struct execute_work {
        struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, TIMER_DEFERRABLE)
 
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
-extern void __init_work(struct work_struct *work, int onstack);
+extern void __init_work(struct work_struct *work);
 extern void destroy_work_on_stack(struct work_struct *work);
 extern void destroy_delayed_work_on_stack(struct delayed_work *work);
 static inline unsigned int work_static(struct work_struct *work)
@@ -207,7 +207,7 @@ static inline unsigned int work_static(struct work_struct *work)
        return *work_data_bits(work) & WORK_STRUCT_STATIC;
 }
 #else
-static inline void __init_work(struct work_struct *work, int onstack) { }
+static inline void __init_work(struct work_struct *work) { }
 static inline void destroy_work_on_stack(struct work_struct *work) { }
 static inline void destroy_delayed_work_on_stack(struct delayed_work *work) { }
 static inline unsigned int work_static(struct work_struct *work) { return 0; }
@@ -221,20 +221,20 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
  * to generate better code.
  */
 #ifdef CONFIG_LOCKDEP
-#define __INIT_WORK(_work, _func, _onstack)                            \
+#define __INIT_WORK(_work, _func)                                      \
        do {                                                            \
                static struct lock_class_key __key;                     \
                                                                        \
-               __init_work((_work), _onstack);                         \
+               __init_work(_work);                                     \
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, &__key, 0); \
                INIT_LIST_HEAD(&(_work)->entry);                        \
                (_work)->func = (_func);                                \
        } while (0)
 #else
-#define __INIT_WORK(_work, _func, _onstack)                            \
+#define __INIT_WORK(_work, _func)                                      \
        do {                                                            \
-               __init_work((_work), _onstack);                         \
+               __init_work(_work);                                     \
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                INIT_LIST_HEAD(&(_work)->entry);                        \
                (_work)->func = (_func);                                \
@@ -242,10 +242,10 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
 #endif
 
 #define INIT_WORK(_work, _func)                                                \
-       __INIT_WORK((_work), (_func), 0)
+       __INIT_WORK((_work), (_func))
 
 #define INIT_WORK_ONSTACK(_work, _func)                                        \
-       __INIT_WORK((_work), (_func), 1)
+       __INIT_WORK((_work), (_func))
 
 #define __INIT_DELAYED_WORK(_work, _func, _tflags)                     \
        do {                                                            \
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 7cd5f5e7e0a1..7d87300cfbc6 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -515,9 +515,9 @@ static inline void debug_work_deactivate(struct work_struct *work)
        debug_object_deactivate(work, &work_debug_descr);
 }
 
-void __init_work(struct work_struct *work, int onstack)
+void __init_work(struct work_struct *work)
 {
-       if (onstack)
+       if (object_is_on_stack(work))
                debug_object_init_on_stack(work, &work_debug_descr);
        else
                debug_object_init(work, &work_debug_descr);

  reply	other threads:[~2022-11-16 21:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-15  1:19 [PATCH] PCI/doe: Fix work struct declaration ira.weiny
2022-11-15 11:13 ` Jonathan Cameron
2022-11-15 19:44 ` Bjorn Helgaas
2022-11-15 20:18   ` Ira Weiny
2022-11-15 20:41     ` Bjorn Helgaas
2022-11-15 20:54       ` Ira Weiny
2022-11-15 22:12         ` Bjorn Helgaas
2022-11-16 10:09 ` Lukas Wunner
2022-11-16 18:20   ` Bjorn Helgaas
2022-11-16 20:57     ` Ira Weiny [this message]
2022-11-16 21:10       ` Dan Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y3VO07WbMI5EYAUD@iweiny-mobl \
    --to=ira.weiny@intel.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=alison.schofield@intel.com \
    --cc=bhelgaas@google.com \
    --cc=bwidawsk@kernel.org \
    --cc=dan.j.williams@intel.com \
    --cc=gregory.price@memverge.com \
    --cc=helgaas@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.