Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Multipath support for RPC
0004  *
0005  * Copyright (c) 2015, 2016, Primary Data, Inc. All rights reserved.
0006  *
0007  * Trond Myklebust <trond.myklebust@primarydata.com>
0008  *
0009  */
0010 #include <linux/atomic.h>
0011 #include <linux/types.h>
0012 #include <linux/kref.h>
0013 #include <linux/list.h>
0014 #include <linux/rcupdate.h>
0015 #include <linux/rculist.h>
0016 #include <linux/slab.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/sunrpc/xprt.h>
0019 #include <linux/sunrpc/addr.h>
0020 #include <linux/sunrpc/xprtmultipath.h>
0021 
0022 #include "sysfs.h"
0023 
0024 typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct rpc_xprt_switch *xps,
0025         const struct rpc_xprt *cur);
0026 
0027 static const struct rpc_xprt_iter_ops rpc_xprt_iter_singular;
0028 static const struct rpc_xprt_iter_ops rpc_xprt_iter_roundrobin;
0029 static const struct rpc_xprt_iter_ops rpc_xprt_iter_listall;
0030 static const struct rpc_xprt_iter_ops rpc_xprt_iter_listoffline;
0031 
0032 static void xprt_switch_add_xprt_locked(struct rpc_xprt_switch *xps,
0033         struct rpc_xprt *xprt)
0034 {
0035     if (unlikely(xprt_get(xprt) == NULL))
0036         return;
0037     list_add_tail_rcu(&xprt->xprt_switch, &xps->xps_xprt_list);
0038     smp_wmb();
0039     if (xps->xps_nxprts == 0)
0040         xps->xps_net = xprt->xprt_net;
0041     xps->xps_nxprts++;
0042     xps->xps_nactive++;
0043 }
0044 
0045 /**
0046  * rpc_xprt_switch_add_xprt - Add a new rpc_xprt to an rpc_xprt_switch
0047  * @xps: pointer to struct rpc_xprt_switch
0048  * @xprt: pointer to struct rpc_xprt
0049  *
0050  * Adds xprt to the end of the list of struct rpc_xprt in xps.
0051  */
0052 void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps,
0053         struct rpc_xprt *xprt)
0054 {
0055     if (xprt == NULL)
0056         return;
0057     spin_lock(&xps->xps_lock);
0058     if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL)
0059         xprt_switch_add_xprt_locked(xps, xprt);
0060     spin_unlock(&xps->xps_lock);
0061     rpc_sysfs_xprt_setup(xps, xprt, GFP_KERNEL);
0062 }
0063 
0064 static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps,
0065         struct rpc_xprt *xprt, bool offline)
0066 {
0067     if (unlikely(xprt == NULL))
0068         return;
0069     if (!test_bit(XPRT_OFFLINE, &xprt->state) && offline)
0070         xps->xps_nactive--;
0071     xps->xps_nxprts--;
0072     if (xps->xps_nxprts == 0)
0073         xps->xps_net = NULL;
0074     smp_wmb();
0075     list_del_rcu(&xprt->xprt_switch);
0076 }
0077 
0078 /**
0079  * rpc_xprt_switch_remove_xprt - Removes an rpc_xprt from a rpc_xprt_switch
0080  * @xps: pointer to struct rpc_xprt_switch
0081  * @xprt: pointer to struct rpc_xprt
0082  * @offline: indicates if the xprt that's being removed is in an offline state
0083  *
0084  * Removes xprt from the list of struct rpc_xprt in xps.
0085  */
0086 void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps,
0087         struct rpc_xprt *xprt, bool offline)
0088 {
0089     spin_lock(&xps->xps_lock);
0090     xprt_switch_remove_xprt_locked(xps, xprt, offline);
0091     spin_unlock(&xps->xps_lock);
0092     xprt_put(xprt);
0093 }
0094 
0095 static DEFINE_IDA(rpc_xprtswitch_ids);
0096 
0097 void xprt_multipath_cleanup_ids(void)
0098 {
0099     ida_destroy(&rpc_xprtswitch_ids);
0100 }
0101 
0102 static int xprt_switch_alloc_id(struct rpc_xprt_switch *xps, gfp_t gfp_flags)
0103 {
0104     int id;
0105 
0106     id = ida_simple_get(&rpc_xprtswitch_ids, 0, 0, gfp_flags);
0107     if (id < 0)
0108         return id;
0109 
0110     xps->xps_id = id;
0111     return 0;
0112 }
0113 
0114 static void xprt_switch_free_id(struct rpc_xprt_switch *xps)
0115 {
0116     ida_simple_remove(&rpc_xprtswitch_ids, xps->xps_id);
0117 }
0118 
0119 /**
0120  * xprt_switch_alloc - Allocate a new struct rpc_xprt_switch
0121  * @xprt: pointer to struct rpc_xprt
0122  * @gfp_flags: allocation flags
0123  *
0124  * On success, returns an initialised struct rpc_xprt_switch, containing
0125  * the entry xprt. Returns NULL on failure.
0126  */
0127 struct rpc_xprt_switch *xprt_switch_alloc(struct rpc_xprt *xprt,
0128         gfp_t gfp_flags)
0129 {
0130     struct rpc_xprt_switch *xps;
0131 
0132     xps = kmalloc(sizeof(*xps), gfp_flags);
0133     if (xps != NULL) {
0134         spin_lock_init(&xps->xps_lock);
0135         kref_init(&xps->xps_kref);
0136         xprt_switch_alloc_id(xps, gfp_flags);
0137         xps->xps_nxprts = xps->xps_nactive = 0;
0138         atomic_long_set(&xps->xps_queuelen, 0);
0139         xps->xps_net = NULL;
0140         INIT_LIST_HEAD(&xps->xps_xprt_list);
0141         xps->xps_iter_ops = &rpc_xprt_iter_singular;
0142         rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags);
0143         xprt_switch_add_xprt_locked(xps, xprt);
0144         xps->xps_nunique_destaddr_xprts = 1;
0145         rpc_sysfs_xprt_setup(xps, xprt, gfp_flags);
0146     }
0147 
0148     return xps;
0149 }
0150 
0151 static void xprt_switch_free_entries(struct rpc_xprt_switch *xps)
0152 {
0153     spin_lock(&xps->xps_lock);
0154     while (!list_empty(&xps->xps_xprt_list)) {
0155         struct rpc_xprt *xprt;
0156 
0157         xprt = list_first_entry(&xps->xps_xprt_list,
0158                 struct rpc_xprt, xprt_switch);
0159         xprt_switch_remove_xprt_locked(xps, xprt, true);
0160         spin_unlock(&xps->xps_lock);
0161         xprt_put(xprt);
0162         spin_lock(&xps->xps_lock);
0163     }
0164     spin_unlock(&xps->xps_lock);
0165 }
0166 
0167 static void xprt_switch_free(struct kref *kref)
0168 {
0169     struct rpc_xprt_switch *xps = container_of(kref,
0170             struct rpc_xprt_switch, xps_kref);
0171 
0172     xprt_switch_free_entries(xps);
0173     rpc_sysfs_xprt_switch_destroy(xps);
0174     xprt_switch_free_id(xps);
0175     kfree_rcu(xps, xps_rcu);
0176 }
0177 
0178 /**
0179  * xprt_switch_get - Return a reference to a rpc_xprt_switch
0180  * @xps: pointer to struct rpc_xprt_switch
0181  *
0182  * Returns a reference to xps unless the refcount is already zero.
0183  */
0184 struct rpc_xprt_switch *xprt_switch_get(struct rpc_xprt_switch *xps)
0185 {
0186     if (xps != NULL && kref_get_unless_zero(&xps->xps_kref))
0187         return xps;
0188     return NULL;
0189 }
0190 
0191 /**
0192  * xprt_switch_put - Release a reference to a rpc_xprt_switch
0193  * @xps: pointer to struct rpc_xprt_switch
0194  *
0195  * Release the reference to xps, and free it once the refcount is zero.
0196  */
0197 void xprt_switch_put(struct rpc_xprt_switch *xps)
0198 {
0199     if (xps != NULL)
0200         kref_put(&xps->xps_kref, xprt_switch_free);
0201 }
0202 
0203 /**
0204  * rpc_xprt_switch_set_roundrobin - Set a round-robin policy on rpc_xprt_switch
0205  * @xps: pointer to struct rpc_xprt_switch
0206  *
0207  * Sets a round-robin default policy for iterators acting on xps.
0208  */
0209 void rpc_xprt_switch_set_roundrobin(struct rpc_xprt_switch *xps)
0210 {
0211     if (READ_ONCE(xps->xps_iter_ops) != &rpc_xprt_iter_roundrobin)
0212         WRITE_ONCE(xps->xps_iter_ops, &rpc_xprt_iter_roundrobin);
0213 }
0214 
0215 static
0216 const struct rpc_xprt_iter_ops *xprt_iter_ops(const struct rpc_xprt_iter *xpi)
0217 {
0218     if (xpi->xpi_ops != NULL)
0219         return xpi->xpi_ops;
0220     return rcu_dereference(xpi->xpi_xpswitch)->xps_iter_ops;
0221 }
0222 
0223 static
0224 void xprt_iter_no_rewind(struct rpc_xprt_iter *xpi)
0225 {
0226 }
0227 
0228 static
0229 void xprt_iter_default_rewind(struct rpc_xprt_iter *xpi)
0230 {
0231     WRITE_ONCE(xpi->xpi_cursor, NULL);
0232 }
0233 
0234 static
0235 bool xprt_is_active(const struct rpc_xprt *xprt)
0236 {
0237     return (kref_read(&xprt->kref) != 0 &&
0238         !test_bit(XPRT_OFFLINE, &xprt->state));
0239 }
0240 
0241 static
0242 struct rpc_xprt *xprt_switch_find_first_entry(struct list_head *head)
0243 {
0244     struct rpc_xprt *pos;
0245 
0246     list_for_each_entry_rcu(pos, head, xprt_switch) {
0247         if (xprt_is_active(pos))
0248             return pos;
0249     }
0250     return NULL;
0251 }
0252 
0253 static
0254 struct rpc_xprt *xprt_switch_find_first_entry_offline(struct list_head *head)
0255 {
0256     struct rpc_xprt *pos;
0257 
0258     list_for_each_entry_rcu(pos, head, xprt_switch) {
0259         if (!xprt_is_active(pos))
0260             return pos;
0261     }
0262     return NULL;
0263 }
0264 
0265 static
0266 struct rpc_xprt *xprt_iter_first_entry(struct rpc_xprt_iter *xpi)
0267 {
0268     struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
0269 
0270     if (xps == NULL)
0271         return NULL;
0272     return xprt_switch_find_first_entry(&xps->xps_xprt_list);
0273 }
0274 
0275 static
0276 struct rpc_xprt *_xprt_switch_find_current_entry(struct list_head *head,
0277                          const struct rpc_xprt *cur,
0278                          bool find_active)
0279 {
0280     struct rpc_xprt *pos;
0281     bool found = false;
0282 
0283     list_for_each_entry_rcu(pos, head, xprt_switch) {
0284         if (cur == pos)
0285             found = true;
0286         if (found && ((find_active && xprt_is_active(pos)) ||
0287                   (!find_active && xprt_is_active(pos))))
0288             return pos;
0289     }
0290     return NULL;
0291 }
0292 
0293 static
0294 struct rpc_xprt *xprt_switch_find_current_entry(struct list_head *head,
0295                         const struct rpc_xprt *cur)
0296 {
0297     return _xprt_switch_find_current_entry(head, cur, true);
0298 }
0299 
0300 static
0301 struct rpc_xprt * _xprt_iter_current_entry(struct rpc_xprt_iter *xpi,
0302         struct rpc_xprt *first_entry(struct list_head *head),
0303         struct rpc_xprt *current_entry(struct list_head *head,
0304                            const struct rpc_xprt *cur))
0305 {
0306     struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
0307     struct list_head *head;
0308 
0309     if (xps == NULL)
0310         return NULL;
0311     head = &xps->xps_xprt_list;
0312     if (xpi->xpi_cursor == NULL || xps->xps_nxprts < 2)
0313         return first_entry(head);
0314     return current_entry(head, xpi->xpi_cursor);
0315 }
0316 
0317 static
0318 struct rpc_xprt *xprt_iter_current_entry(struct rpc_xprt_iter *xpi)
0319 {
0320     return _xprt_iter_current_entry(xpi, xprt_switch_find_first_entry,
0321             xprt_switch_find_current_entry);
0322 }
0323 
0324 static
0325 struct rpc_xprt *xprt_switch_find_current_entry_offline(struct list_head *head,
0326         const struct rpc_xprt *cur)
0327 {
0328     return _xprt_switch_find_current_entry(head, cur, false);
0329 }
0330 
0331 static
0332 struct rpc_xprt *xprt_iter_current_entry_offline(struct rpc_xprt_iter *xpi)
0333 {
0334     return _xprt_iter_current_entry(xpi,
0335             xprt_switch_find_first_entry_offline,
0336             xprt_switch_find_current_entry_offline);
0337 }
0338 
0339 bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
0340                   const struct sockaddr *sap)
0341 {
0342     struct list_head *head;
0343     struct rpc_xprt *pos;
0344 
0345     if (xps == NULL || sap == NULL)
0346         return false;
0347 
0348     head = &xps->xps_xprt_list;
0349     list_for_each_entry_rcu(pos, head, xprt_switch) {
0350         if (rpc_cmp_addr_port(sap, (struct sockaddr *)&pos->addr)) {
0351             pr_info("RPC:   addr %s already in xprt switch\n",
0352                 pos->address_strings[RPC_DISPLAY_ADDR]);
0353             return true;
0354         }
0355     }
0356     return false;
0357 }
0358 
0359 static
0360 struct rpc_xprt *xprt_switch_find_next_entry(struct list_head *head,
0361         const struct rpc_xprt *cur, bool check_active)
0362 {
0363     struct rpc_xprt *pos, *prev = NULL;
0364     bool found = false;
0365 
0366     list_for_each_entry_rcu(pos, head, xprt_switch) {
0367         if (cur == prev)
0368             found = true;
0369         /* for request to return active transports return only
0370          * active, for request to return offline transports
0371          * return only offline
0372          */
0373         if (found && ((check_active && xprt_is_active(pos)) ||
0374                   (!check_active && !xprt_is_active(pos))))
0375             return pos;
0376         prev = pos;
0377     }
0378     return NULL;
0379 }
0380 
0381 static
0382 struct rpc_xprt *xprt_switch_set_next_cursor(struct rpc_xprt_switch *xps,
0383         struct rpc_xprt **cursor,
0384         xprt_switch_find_xprt_t find_next)
0385 {
0386     struct rpc_xprt *pos, *old;
0387 
0388     old = smp_load_acquire(cursor);
0389     pos = find_next(xps, old);
0390     smp_store_release(cursor, pos);
0391     return pos;
0392 }
0393 
0394 static
0395 struct rpc_xprt *xprt_iter_next_entry_multiple(struct rpc_xprt_iter *xpi,
0396         xprt_switch_find_xprt_t find_next)
0397 {
0398     struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
0399 
0400     if (xps == NULL)
0401         return NULL;
0402     return xprt_switch_set_next_cursor(xps, &xpi->xpi_cursor, find_next);
0403 }
0404 
0405 static
0406 struct rpc_xprt *__xprt_switch_find_next_entry_roundrobin(struct list_head *head,
0407         const struct rpc_xprt *cur)
0408 {
0409     struct rpc_xprt *ret;
0410 
0411     ret = xprt_switch_find_next_entry(head, cur, true);
0412     if (ret != NULL)
0413         return ret;
0414     return xprt_switch_find_first_entry(head);
0415 }
0416 
0417 static
0418 struct rpc_xprt *xprt_switch_find_next_entry_roundrobin(struct rpc_xprt_switch *xps,
0419         const struct rpc_xprt *cur)
0420 {
0421     struct list_head *head = &xps->xps_xprt_list;
0422     struct rpc_xprt *xprt;
0423     unsigned int nactive;
0424 
0425     for (;;) {
0426         unsigned long xprt_queuelen, xps_queuelen;
0427 
0428         xprt = __xprt_switch_find_next_entry_roundrobin(head, cur);
0429         if (!xprt)
0430             break;
0431         xprt_queuelen = atomic_long_read(&xprt->queuelen);
0432         xps_queuelen = atomic_long_read(&xps->xps_queuelen);
0433         nactive = READ_ONCE(xps->xps_nactive);
0434         /* Exit loop if xprt_queuelen <= average queue length */
0435         if (xprt_queuelen * nactive <= xps_queuelen)
0436             break;
0437         cur = xprt;
0438     }
0439     return xprt;
0440 }
0441 
0442 static
0443 struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)
0444 {
0445     return xprt_iter_next_entry_multiple(xpi,
0446             xprt_switch_find_next_entry_roundrobin);
0447 }
0448 
0449 static
0450 struct rpc_xprt *xprt_switch_find_next_entry_all(struct rpc_xprt_switch *xps,
0451         const struct rpc_xprt *cur)
0452 {
0453     return xprt_switch_find_next_entry(&xps->xps_xprt_list, cur, true);
0454 }
0455 
0456 static
0457 struct rpc_xprt *xprt_switch_find_next_entry_offline(struct rpc_xprt_switch *xps,
0458         const struct rpc_xprt *cur)
0459 {
0460     return xprt_switch_find_next_entry(&xps->xps_xprt_list, cur, false);
0461 }
0462 
0463 static
0464 struct rpc_xprt *xprt_iter_next_entry_all(struct rpc_xprt_iter *xpi)
0465 {
0466     return xprt_iter_next_entry_multiple(xpi,
0467             xprt_switch_find_next_entry_all);
0468 }
0469 
0470 static
0471 struct rpc_xprt *xprt_iter_next_entry_offline(struct rpc_xprt_iter *xpi)
0472 {
0473     return xprt_iter_next_entry_multiple(xpi,
0474             xprt_switch_find_next_entry_offline);
0475 }
0476 
0477 /*
0478  * xprt_iter_rewind - Resets the xprt iterator
0479  * @xpi: pointer to rpc_xprt_iter
0480  *
0481  * Resets xpi to ensure that it points to the first entry in the list
0482  * of transports.
0483  */
0484 void xprt_iter_rewind(struct rpc_xprt_iter *xpi)
0485 {
0486     rcu_read_lock();
0487     xprt_iter_ops(xpi)->xpi_rewind(xpi);
0488     rcu_read_unlock();
0489 }
0490 
0491 static void __xprt_iter_init(struct rpc_xprt_iter *xpi,
0492         struct rpc_xprt_switch *xps,
0493         const struct rpc_xprt_iter_ops *ops)
0494 {
0495     rcu_assign_pointer(xpi->xpi_xpswitch, xprt_switch_get(xps));
0496     xpi->xpi_cursor = NULL;
0497     xpi->xpi_ops = ops;
0498 }
0499 
0500 /**
0501  * xprt_iter_init - Initialise an xprt iterator
0502  * @xpi: pointer to rpc_xprt_iter
0503  * @xps: pointer to rpc_xprt_switch
0504  *
0505  * Initialises the iterator to use the default iterator ops
0506  * as set in xps. This function is mainly intended for internal
0507  * use in the rpc_client.
0508  */
0509 void xprt_iter_init(struct rpc_xprt_iter *xpi,
0510         struct rpc_xprt_switch *xps)
0511 {
0512     __xprt_iter_init(xpi, xps, NULL);
0513 }
0514 
0515 /**
0516  * xprt_iter_init_listall - Initialise an xprt iterator
0517  * @xpi: pointer to rpc_xprt_iter
0518  * @xps: pointer to rpc_xprt_switch
0519  *
0520  * Initialises the iterator to iterate once through the entire list
0521  * of entries in xps.
0522  */
0523 void xprt_iter_init_listall(struct rpc_xprt_iter *xpi,
0524         struct rpc_xprt_switch *xps)
0525 {
0526     __xprt_iter_init(xpi, xps, &rpc_xprt_iter_listall);
0527 }
0528 
0529 void xprt_iter_init_listoffline(struct rpc_xprt_iter *xpi,
0530         struct rpc_xprt_switch *xps)
0531 {
0532     __xprt_iter_init(xpi, xps, &rpc_xprt_iter_listoffline);
0533 }
0534 
0535 /**
0536  * xprt_iter_xchg_switch - Atomically swap out the rpc_xprt_switch
0537  * @xpi: pointer to rpc_xprt_iter
0538  * @newswitch: pointer to a new rpc_xprt_switch or NULL
0539  *
0540  * Swaps out the existing xpi->xpi_xpswitch with a new value.
0541  */
0542 struct rpc_xprt_switch *xprt_iter_xchg_switch(struct rpc_xprt_iter *xpi,
0543         struct rpc_xprt_switch *newswitch)
0544 {
0545     struct rpc_xprt_switch __rcu *oldswitch;
0546 
0547     /* Atomically swap out the old xpswitch */
0548     oldswitch = xchg(&xpi->xpi_xpswitch, RCU_INITIALIZER(newswitch));
0549     if (newswitch != NULL)
0550         xprt_iter_rewind(xpi);
0551     return rcu_dereference_protected(oldswitch, true);
0552 }
0553 
0554 /**
0555  * xprt_iter_destroy - Destroys the xprt iterator
0556  * @xpi: pointer to rpc_xprt_iter
0557  */
0558 void xprt_iter_destroy(struct rpc_xprt_iter *xpi)
0559 {
0560     xprt_switch_put(xprt_iter_xchg_switch(xpi, NULL));
0561 }
0562 
0563 /**
0564  * xprt_iter_xprt - Returns the rpc_xprt pointed to by the cursor
0565  * @xpi: pointer to rpc_xprt_iter
0566  *
0567  * Returns a pointer to the struct rpc_xprt that is currently
0568  * pointed to by the cursor.
0569  * Caller must be holding rcu_read_lock().
0570  */
0571 struct rpc_xprt *xprt_iter_xprt(struct rpc_xprt_iter *xpi)
0572 {
0573     WARN_ON_ONCE(!rcu_read_lock_held());
0574     return xprt_iter_ops(xpi)->xpi_xprt(xpi);
0575 }
0576 
0577 static
0578 struct rpc_xprt *xprt_iter_get_helper(struct rpc_xprt_iter *xpi,
0579         struct rpc_xprt *(*fn)(struct rpc_xprt_iter *))
0580 {
0581     struct rpc_xprt *ret;
0582 
0583     do {
0584         ret = fn(xpi);
0585         if (ret == NULL)
0586             break;
0587         ret = xprt_get(ret);
0588     } while (ret == NULL);
0589     return ret;
0590 }
0591 
0592 /**
0593  * xprt_iter_get_xprt - Returns the rpc_xprt pointed to by the cursor
0594  * @xpi: pointer to rpc_xprt_iter
0595  *
0596  * Returns a reference to the struct rpc_xprt that is currently
0597  * pointed to by the cursor.
0598  */
0599 struct rpc_xprt *xprt_iter_get_xprt(struct rpc_xprt_iter *xpi)
0600 {
0601     struct rpc_xprt *xprt;
0602 
0603     rcu_read_lock();
0604     xprt = xprt_iter_get_helper(xpi, xprt_iter_ops(xpi)->xpi_xprt);
0605     rcu_read_unlock();
0606     return xprt;
0607 }
0608 
0609 /**
0610  * xprt_iter_get_next - Returns the next rpc_xprt following the cursor
0611  * @xpi: pointer to rpc_xprt_iter
0612  *
0613  * Returns a reference to the struct rpc_xprt that immediately follows the
0614  * entry pointed to by the cursor.
0615  */
0616 struct rpc_xprt *xprt_iter_get_next(struct rpc_xprt_iter *xpi)
0617 {
0618     struct rpc_xprt *xprt;
0619 
0620     rcu_read_lock();
0621     xprt = xprt_iter_get_helper(xpi, xprt_iter_ops(xpi)->xpi_next);
0622     rcu_read_unlock();
0623     return xprt;
0624 }
0625 
0626 /* Policy for always returning the first entry in the rpc_xprt_switch */
0627 static
0628 const struct rpc_xprt_iter_ops rpc_xprt_iter_singular = {
0629     .xpi_rewind = xprt_iter_no_rewind,
0630     .xpi_xprt = xprt_iter_first_entry,
0631     .xpi_next = xprt_iter_first_entry,
0632 };
0633 
0634 /* Policy for round-robin iteration of entries in the rpc_xprt_switch */
0635 static
0636 const struct rpc_xprt_iter_ops rpc_xprt_iter_roundrobin = {
0637     .xpi_rewind = xprt_iter_default_rewind,
0638     .xpi_xprt = xprt_iter_current_entry,
0639     .xpi_next = xprt_iter_next_entry_roundrobin,
0640 };
0641 
0642 /* Policy for once-through iteration of entries in the rpc_xprt_switch */
0643 static
0644 const struct rpc_xprt_iter_ops rpc_xprt_iter_listall = {
0645     .xpi_rewind = xprt_iter_default_rewind,
0646     .xpi_xprt = xprt_iter_current_entry,
0647     .xpi_next = xprt_iter_next_entry_all,
0648 };
0649 
0650 static
0651 const struct rpc_xprt_iter_ops rpc_xprt_iter_listoffline = {
0652     .xpi_rewind = xprt_iter_default_rewind,
0653     .xpi_xprt = xprt_iter_current_entry_offline,
0654     .xpi_next = xprt_iter_next_entry_offline,
0655 };