Hi Anatoly: Sorry to miss this email and reply late. > -----Original Message----- > From: Burakov, Anatoly > Sent: Friday, June 15, 2018 11:43 PM > To: Zhang, Qi Z <qi.z.zh...@intel.com>; tho...@monjalon.net > Cc: Ananyev, Konstantin <konstantin.anan...@intel.com>; dev@dpdk.org; > Richardson, Bruce <bruce.richard...@intel.com>; Yigit, Ferruh > <ferruh.yi...@intel.com>; Shelton, Benjamin H > <benjamin.h.shel...@intel.com>; Vangati, Narender > <narender.vang...@intel.com> > Subject: Re: [PATCH 05/22] ethdev: introduce device lock > > On 07-Jun-18 1:38 PM, Qi Zhang wrote: > > Introduce API rte_eth_dev_lock and rte_eth_dev_unlock to let > > application lock or unlock on specific ethdev, a locked device can't > > be detached, this help applicaiton to prevent unexpected device > > detaching, especially in multi-process envrionment. > > > > Aslo the new API let application to register a callback function which > > will be invoked before a device is going to be detached, the return > > value of the function will decide if device will continue be detached > > or not, this support application to do condition check at runtime. > > > > Signed-off-by: Qi Zhang <qi.z.zh...@intel.com> > > --- > > <snip> > > > + > > +int > > +rte_eth_dev_lock(uint16_t port_id, rte_eth_dev_lock_callback_t callback, > > + void *user_args) > > +{ > > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); > > + > > + if (callback == NULL) > > + return register_lock_callback(port_id, dev_is_busy, NULL); > > + else > > + return register_lock_callback(port_id, callback, user_args); > > As much as i don't like seeing negative errno values as return, the rest of > ethdev library uses those, so this is OK :) > > > +} > > + > > +int > > +rte_eth_dev_unlock(uint16_t port_id, rte_eth_dev_lock_callback_t callback, > > + void *user_args) > > +{ > > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); > > + > > <snip> > > > + * Also, any callback function return !0 value will prevent device be > > + * detached(ref. rte_eth_dev_lock and rte_eth_dev_unlock). > > + * > > + * @param port_id > > + * The port identifier of the Ethernet device. > > + * @param user_args > > + * This is parameter "user_args" be saved when callback function is > > + * registered(rte_dev_eth_lock). > > + * > > + * @return > > + * 0 device is allowed be detached. > > + * !0 device is not allowed be detached. > > !0 can be negative or positive. Are we expecting positive return values from > this API?
I have no strong opinion, but if you think below or other option is better, I can change >=0 device is allowed be detached. <0 device is not allowed be detached. > > > + */ > > +typedef int (*rte_eth_dev_lock_callback_t)(uint16_t port_id, void > > +*user_args); > > + > > +/** > > + * Lock an Ethernet Device directly or register a callback function > > + * for condition check at runtime, this help application to prevent > > + * a device be detached unexpectedly > > + * NOTE: Lock a device multiple times with same parmeter will > > +increase > > + * a ref_count, and corresponding unlock decrease the ref_count, the > > + * device will be unlocked when ref_count reach 0. > > Nitpick: "note" sections should be done with @note marker. > > Also, i would mention that this is a per-process lock that does not affect > other > processes (assuming i understood the code correctly, of course...). OK, I will add more comment to explain this. > > > + * > > + * @param port_id > > + * The port identifier of the Ethernet device. > > + * @param callback > > + * !NULL the callback function will be added into a pre-detach list, > > + * it will be invoked when a device is going to be detached. The > > + * return value will decide if continue detach the device or not. > > + * NULL lock the device directly, basically this just regiter a empty > > + * callback function(dev_is_busy) that return -EBUSY, so we can > > + * handle the pre-detach check in unified way. > > + * @param user_args > > + * parameter will be parsed to callback function, only valid when > > + * callback != NULL. > > + * @return > > + * 0 on success, negative on error. > > + */ > > +int rte_eth_dev_lock(uint16_t port_id, rte_eth_dev_lock_callback_t > callback, > > + void *user_args); > > Nitpicks: DPDK style guide discourages using spaces as indentation (other > parts > of this patch, and other patches have this issue as well). OK, will fix all. > > > + > > +/** > > + * Reverse operation of rte_eth_dev_lock. > > + * > > + * @param port_id > > + * The port identifier of the Ethernet device. > > + * @param callback > > + * NULL decrease the ref_count of default callback function. > > + * !NULL decrease the ref_count of specific callback with matched > > + * user_args. > > + * @param user_args > > + * parameter to match, only valid when callback != NULL. > > + * @return > > + * 0 on success, negative on error. > > + */ > > +int rte_eth_dev_unlock(uint16_t port_id, rte_eth_dev_lock_callback_t > callback, > > + void *user_args); > > + > > #ifdef __cplusplus > > } > > #endif > > diff --git a/lib/librte_ethdev/rte_ethdev_lock.c > > b/lib/librte_ethdev/rte_ethdev_lock.c > > rte_ethdev_lock.* seem to be internal-only files. Perhaps you should name > them without the rte_ prefix to indicate that they're not exported? > > > new file mode 100644 > > index 000000000..688d1d70a > > --- /dev/null > > +++ b/lib/librte_ethdev/rte_ethdev_lock.c > > @@ -0,0 +1,102 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright(c) 2018 Intel Corporation */ #include > > +"rte_ethdev_lock.h" > > + > > +struct lock_entry { > > + TAILQ_ENTRY(lock_entry) next; > > + rte_eth_dev_lock_callback_t callback; > > + uint16_t port_id; > > <snip> > > > +register_lock_callback(uint16_t port_id, > > + rte_eth_dev_lock_callback_t callback, > > + void *user_args) > > +{ > > + struct lock_entry *le; > > + > > + rte_spinlock_lock(&lock_entry_lock); > > + > > + TAILQ_FOREACH(le, &lock_entry_list, next) { > > + if (le->port_id == port_id && > > + le->callback == callback && > > + le->user_args == user_args) > > + break; > > + } > > + > > + if (!le) { > > + le = calloc(1, sizeof(struct lock_entry)); > > + if (!le) { > > Nitpick: generally, DPDK style guide prefers "if (value)" or "if (!value)" to > only > be reserved for boolean values, and use explicit comparison (e.g. "if (value > == > NULL)" or "if (value == 0)") for all other cases. OK, will fix > > -- > Thanks, > Anatoly