On 06/09/14 at 03:26pm, Andy Zhou wrote: > On Mon, Jun 9, 2014 at 2:58 PM, Thomas Graf <tg...@suug.ch> wrote: > > On 06/06/14 at 02:37pm, Andy Zhou wrote: > >> +static void tbl_mask_array_delete_mask(struct mask_array *ma, > >> + const struct sw_flow_mask *mask) > >> +{ > >> + int i = 0; > >> + > >> + /* Delete a mask pointer from the valid section. > >> + * > >> + * Also move the last entry in its place, so there is no > >> + * whole in the valid section. > >> + * > >> + * Notice the last entry still points to the original mask. > >> + * > >> + * <Note>: there is a small race window that may cause a mask > >> + * to be missed in a search. Imaging a core is > >> + * walking through the array, passing the index of deleting mask. > >> + * But before reaching the last entry, it is overwritten, > >> + * by another core that is adding a new mask, now the last entry > >> + * will point to the new mask. In this case, the moved up last > >> + * entry can be missed by the core walking the mask array. > >> + * > >> + * In case this missed mask would have led to successful > >> + * lookup, Hitting the race window could cause a packet to miss > >> + * kernel flow cache, and be sent to the user space. > >> + * </Note> > >> + */ > >> + while (i < ma->count - 1) { > > > > I think this should be coded as a for (;;) loop instead of > > incrementing `i` in the else branch. > I agree for loop would be easier to read, but in this case, I need > to reconsider the just reloaded entry, so "i" will only move up if > no deletion happens. It is not clear to me how to structure it as a for loop.
I think you could make it work as you stop iterating upon deletion, like this: for (i = 0; i < ma->count - 1; i++) { if (mask == ma->masks[i]) { [...] break; } } This is also how other similar kernel code looks like. _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev