On Mon, Dec 07, 2020 at 05:09:37PM -0800, Jakub Kicinski wrote: > > + ocelot->owq = alloc_ordered_workqueue("ocelot-owq", WQ_MEM_RECLAIM); > > Why MEM_RECLAIM ?
Ok, fine, I admit, I copied it. After reading the documentation a bit more thoroughly, I am still as clear about the guidelines as before. The original logic was, I am allocating a memory area and then freeing it from the work item. So it must be beneficial for the kernel to want to flush this workqueue during the memory reclaim process / under memory pressure, because I am doing no memory allocation, and I am also freeing some memory in fact. The thing is, there are already a lot of users of WQ_MEM_RECLAIM. Many outside of the filesystem/block subsystems. Not sure if all of them misuse it, or how to even tell which one constitutes a correct example of usage for WQ_MEM_RECLAIM. > > + if (!ocelot->owq) > > + return -ENOMEM; > > I don't think you can pass NULL to destroy_workqueue() so IDK how this > code does error handling (freeing of ocelot->stats_queue if owq fails). It doesn't. > > INIT_LIST_HEAD(&ocelot->multicast); > > INIT_LIST_HEAD(&ocelot->pgids); > > ocelot_mact_init(ocelot); > > @@ -1619,6 +1623,7 @@ void ocelot_deinit(struct ocelot *ocelot) > > { > > cancel_delayed_work(&ocelot->stats_work); > > destroy_workqueue(ocelot->stats_queue); > > + destroy_workqueue(ocelot->owq); > > mutex_destroy(&ocelot->stats_lock); > > } > > > +static int ocelot_enqueue_mact_action(struct ocelot *ocelot, > > + const struct ocelot_mact_work_ctx *ctx) > > +{ > > + struct ocelot_mact_work_ctx *w = kmalloc(sizeof(*w), GFP_ATOMIC); > > + > > + if (!w) > > + return -ENOMEM; > > + > > + memcpy(w, ctx, sizeof(*w)); > > kmemdup()? Ok.