Re: [PATCH 7/8] RDMA/devices: Use xarray to store the client_data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 04, 2019 at 10:15:20PM -0700, Jason Gunthorpe wrote:
> > > > I'm not familiar enough with your code to figure out where you'd want
> > > > to rcu_read_unlock() :-)
> > > 
> > > Hum, it barely matters, but just after the if would be fine and
> > > slightly fewer pauses. This thing only has about 5 entries in it. I
> > > often wonder why it was made dynamic at all.
> > 
> > Cool.  Just remember to call xas_reset() if you drop the rcu read lock
> > and continue the loop.
> 
> xas_reset? Did you mean xas_pause?
> 
> I guess the full version looks like this:
> 
> 	down_read(&dev->client_data_rwsem);
> 	rcu_read_lock();
> 	xas_for_each_marked(&xas, client_data, ULONG_MAX,
> 			    CLIENT_DATA_REGISTERED) {
> 		struct ib_client *client;
> 
> 		if (!xa_is_zero(entry) && xas_retry(&xas, client_data))
> 			continue;

Rather looks like this needs to check for XA_FREE_MARK too...

> 		client = xa_load(&clients, xas.xa_index);
> 		if (!client || !client->get_net_dev_by_params)
> 			continue;
> 
>                 xas_pause();
> 		rcu_read_unlock();
> 
> 		net_dev = client->get_net_dev_by_params(dev, port, pkey, gid,
> 							addr, client_data);
> 		rcu_read_lock();
> 		if (net_dev)
> 			break;
> 
> 	}
> 	rcu_read_unlock();
> 	up_read(&dev->client_data_rwsem);
> 
> Doesn't do much for readability :)

Ah.. Unless you feel strongly I think I'll stick with just changing
the macro version to use xa_err .. this becomes too much confounding
stuff in what should have been a simple function.

/*
 * xarray has this behavior where it won't iterate over NULL values stored in
 * allocated arrays.  So we need our own iterator to see all values stored in
 * the array. This does the same thing as xa_for_each except that it also
 * returns NULL valued entries if the array is allocating. Simplified to only
 * work on simple xarrays.
 */
static void *xan_find_marked(struct xarray *xa, unsigned long *indexp,
			     xa_mark_t filter)
{
	XA_STATE(xas, xa, *indexp);
	void *entry;

	rcu_read_lock();
	do {
		entry = xas_find_marked(&xas, ULONG_MAX, filter);
		if (xa_is_zero(entry) && !xas_get_mark(&xas, XA_FREE_MARK))
			break;
	} while (xas_retry(&xas, entry));
	rcu_read_unlock();

	if (entry) {
		*indexp = xas.xa_index;
		if (xa_is_zero(entry))
			return NULL;
		return entry;
	}
	return XA_ERROR(-ENOENT);
}
#define xan_for_each_marked(xa, index, entry, filter)                          \
	for (index = 0, entry = xan_find_marked(xa, &(index), filter);         \
	     !xa_is_err(entry);                                                \
	     (index)++, entry = xan_find_marked(xa, &(index), filter))

Thanks,
Jason



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux