#include <linux/inet.h>
#include <linux/in6.h>
#include <linux/slab.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
#include <linux/sunrpc/bc_xprt.h>
EXPORT_SYMBOL_GPL(nfs_alloc_client);
#if IS_ENABLED(CONFIG_NFS_V4)
-static void nfs_cleanup_cb_ident_idr(struct net *net)
+static void nfs_cleanup_cb_ident(struct nfs_net *nn)
{
- struct nfs_net *nn = net_generic(net, nfs_net_id);
-
- idr_destroy(&nn->cb_ident_idr);
+ xa_destroy(&nn->cb_ids);
}
-/* nfs_client_lock held */
-static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+static void nfs_cb_id_remove_locked(struct nfs_net *nn, struct nfs_client *clp)
{
- struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
-
if (clp->cl_cb_ident)
- idr_remove(&nn->cb_ident_idr, clp->cl_cb_ident);
+ xa_erase(&nn->cb_ids, clp->cl_cb_ident);
}
static void pnfs_init_server(struct nfs_server *server)
}
#else
-static void nfs_cleanup_cb_ident_idr(struct net *net)
+static void nfs_cleanup_cb_ident(struct nfs_net *nn)
{
}
-static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+static void nfs_cb_id_remove_locked(struct nfs_net *nn, struct nfs_client *clp)
{
}
if (refcount_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
list_del(&clp->cl_share_link);
- nfs_cb_idr_remove_locked(clp);
+ nfs_cb_id_remove_locked(nn, clp);
spin_unlock(&nn->nfs_client_lock);
WARN_ON_ONCE(!list_empty(&clp->cl_superblocks));
INIT_LIST_HEAD(&nn->nfs_client_list);
INIT_LIST_HEAD(&nn->nfs_volume_list);
#if IS_ENABLED(CONFIG_NFS_V4)
- idr_init(&nn->cb_ident_idr);
+ xa_init_flags(&nn->cb_ids, XA_FLAGS_ALLOC1);
#endif
spin_lock_init(&nn->nfs_client_lock);
nn->boot_time = ktime_get_real();
struct nfs_net *nn = net_generic(net, nfs_net_id);
nfs_netns_sysfs_destroy(nn);
- nfs_cleanup_cb_ident_idr(net);
+ nfs_cleanup_cb_ident(nn);
WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
}
struct list_head nfs_client_list;
struct list_head nfs_volume_list;
#if IS_ENABLED(CONFIG_NFS_V4)
- struct idr cb_ident_idr; /* Protected by nfs_client_lock */
+ struct xarray cb_ids;
unsigned short nfs_callback_tcpport;
unsigned short nfs_callback_tcpport6;
int cb_users[NFS4_MAX_MINOR_VERSION + 1];
* Get a unique NFSv4.0 callback identifier which will be used
* by the V4.0 callback service to lookup the nfs_client struct
*/
-static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
+static int nfs_get_cb_ident(struct nfs_client *clp, int minorversion)
{
- int ret = 0;
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
if (clp->rpc_ops->version != 4 || minorversion != 0)
- return ret;
- idr_preload(GFP_KERNEL);
- spin_lock(&nn->nfs_client_lock);
- ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT);
- if (ret >= 0)
- clp->cl_cb_ident = ret;
- spin_unlock(&nn->nfs_client_lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ return 0;
+ return xa_alloc(&nn->cb_ids, &clp->cl_cb_ident, clp, xa_limit_32b,
+ GFP_KERNEL);
}
#ifdef CONFIG_NFS_V4_1
if (IS_ERR(clp))
return clp;
- err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ err = nfs_get_cb_ident(clp, cl_init->minorversion);
if (err)
goto error;
dprintk("%s: keeping callback ident %u and dropping ident %u\n",
__func__, keep->cl_cb_ident, drop->cl_cb_ident);
- spin_lock(&nn->nfs_client_lock);
-
- idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident);
+ xa_lock(&nn->cb_ids);
+ __xa_store(&nn->cb_ids, drop->cl_cb_ident, keep, 0);
keep->cl_cb_ident = drop->cl_cb_ident;
-
- idr_replace(&nn->cb_ident_idr, drop, save);
+ __xa_store(&nn->cb_ids, save, drop, 0);
drop->cl_cb_ident = save;
-
- spin_unlock(&nn->nfs_client_lock);
+ xa_unlock(&nn->cb_ids);
}
static bool nfs4_match_client_owner_id(const struct nfs_client *clp1,
struct nfs_client *clp;
struct nfs_net *nn = net_generic(net, nfs_net_id);
- spin_lock(&nn->nfs_client_lock);
- clp = idr_find(&nn->cb_ident_idr, cb_ident);
+ xa_lock(&nn->cb_ids);
+ clp = xa_load(&nn->cb_ids, cb_ident);
if (clp)
refcount_inc(&clp->cl_count);
- spin_unlock(&nn->nfs_client_lock);
+ xa_unlock(&nn->cb_ids);
return clp;
}