On Fri, 2013-12-13 at 15:59 -0800, Andy Grover wrote:
> Instead of an array, use a rbtree. Less memory use on average, and
> can allow >255 entries. We go from O(1) to O(log n) on lookups. If this
> shows up on profiling (it won't) then transition to other kernel lookup
> methods is straightforward from here.
> 

Ugh.

There is no reason to be using rbtrees in a performance critical path
here.

The number of pointer lookups is what ends up hurting the most vs. a
flat array, so given that 256 LUNs per endpoint is currently not an
issue, and there is no hard limit on the number of endpoints with
virtual addressing, I don't see the benefit of this patch.

NAK.

--nab

> Change core_disable_device_list_for_node to be called with device_list_lock
> held, and tweaked params a little.
> 
> TRANSPORT_LUNFLAGS_INITIATOR_ACCESS no longer needed, presence in the
> rbtree is equivalent to this being set.
> 
> Signed-off-by: Andy Grover <agro...@redhat.com>
> ---
>  drivers/target/target_core_device.c          |  213 ++++++++++++++-----------
>  drivers/target/target_core_fabric_configfs.c |   24 ++--
>  drivers/target/target_core_internal.h        |   15 +-
>  drivers/target/target_core_pr.c              |   25 +++-
>  drivers/target/target_core_spc.c             |   11 +-
>  drivers/target/target_core_stat.c            |   72 +++++-----
>  drivers/target/target_core_tpg.c             |   53 +------
>  drivers/target/target_core_ua.c              |   18 ++-
>  include/target/target_core_base.h            |    8 +-
>  9 files changed, 222 insertions(+), 217 deletions(-)
> 
> diff --git a/drivers/target/target_core_device.c 
> b/drivers/target/target_core_device.c
> index af12456..a18724b 100644
> --- a/drivers/target/target_core_device.c
> +++ b/drivers/target/target_core_device.c
> @@ -54,6 +54,51 @@ static struct se_hba *lun0_hba;
>  /* not static, needed by tpg.c */
>  struct se_device *g_lun0_dev;
>  
> +bool transport_insert_deve(struct se_node_acl *nacl, struct se_dev_entry 
> *deve)
> +{
> +     struct rb_root *root = &nacl->rb_device_list;
> +     struct rb_node **new = &(root->rb_node), *parent = NULL;
> +
> +     /* Figure out where to put new node */
> +     while (*new) {
> +             struct se_dev_entry *this = rb_entry(*new, struct se_dev_entry, 
> rb_node);
> +
> +             parent = *new;
> +             if (deve->mapped_lun < this->mapped_lun)
> +                     new = &((*new)->rb_left);
> +             else if (deve->mapped_lun > this->mapped_lun)
> +                     new = &((*new)->rb_right);
> +             else
> +                     return false;
> +     }
> +
> +     /* Add new node and rebalance tree. */
> +     rb_link_node(&deve->rb_node, parent, new);
> +     rb_insert_color(&deve->rb_node, root);
> +
> +     return true;
> +}
> +
> +
> +struct se_dev_entry *transport_search_deve(struct se_node_acl *nacl, u32 
> mapped_lun)
> +{
> +     struct rb_root *root = &nacl->rb_device_list;
> +     struct rb_node *node = root->rb_node;
> +
> +     while (node) {
> +             struct se_dev_entry *deve = rb_entry(node, struct se_dev_entry, 
> rb_node);
> +
> +             if (mapped_lun < deve->mapped_lun)
> +                     node = node->rb_left;
> +             else if (mapped_lun > deve->mapped_lun)
> +                     node = node->rb_right;
> +             else
> +                     return deve;
> +     }
> +     return NULL;
> +}
> +
> +
>  sense_reason_t
>  transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
>  {
> @@ -66,8 +111,8 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 
> unpacked_lun)
>               return TCM_NON_EXISTENT_LUN;
>  
>       spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
> -     se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
> -     if (se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
> +     se_cmd->se_deve = transport_search_deve(se_sess->se_node_acl, 
> unpacked_lun);
> +     if (se_cmd->se_deve) {
>               struct se_dev_entry *deve = se_cmd->se_deve;
>  
>               deve->total_cmds++;
> @@ -153,10 +198,10 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 
> unpacked_lun)
>               return -ENODEV;
>  
>       spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
> -     se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
> -     deve = se_cmd->se_deve;
> +     se_cmd->se_deve = transport_search_deve(se_sess->se_node_acl, 
> unpacked_lun);
> +     if (se_cmd->se_deve) {
> +             deve = se_cmd->se_deve;
>  
> -     if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
>               se_tmr->tmr_lun = deve->se_lun;
>               se_cmd->se_lun = deve->se_lun;
>               se_lun = deve->se_lun;
> @@ -187,25 +232,22 @@ EXPORT_SYMBOL(transport_lookup_tmr_lun);
>  
>  /*
>   * This function is called from core_scsi3_emulate_pro_register_and_move()
> - * and core_scsi3_decode_spec_i_port(), and will increment 
> &deve->pr_ref_count
> + * and core_scsi3_decode_spec_i_port(), and will increment deve->refcount
>   * when a matching rtpi is found.
>   */
>  struct se_dev_entry *core_get_se_deve_from_rtpi(
>       struct se_node_acl *nacl,
>       u16 rtpi)
>  {
> -     struct se_dev_entry *deve;
>       struct se_lun *lun;
>       struct se_port *port;
>       struct se_portal_group *tpg = nacl->se_tpg;
> -     u32 i;
> +     struct rb_node *node;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -             deve = nacl->device_list[i];
> -
> -             if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
> -                     continue;
> +     for (node = rb_first(&nacl->rb_device_list); node; node = rb_next(node))
> +     {
> +             struct se_dev_entry *deve = rb_entry(node, struct se_dev_entry, 
> rb_node);
>  
>               lun = deve->se_lun;
>               if (!lun) {
> @@ -234,43 +276,24 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
>       return NULL;
>  }
>  
> -int core_free_device_list_for_node(
> +void core_free_device_list_for_node(
>       struct se_node_acl *nacl,
>       struct se_portal_group *tpg)
>  {
> -     struct se_dev_entry *deve;
> -     struct se_lun *lun;
> -     u32 i;
> -
> -     if (!nacl->device_list)
> -             return 0;
> +     struct se_dev_entry *deve, *_tmp;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -             deve = nacl->device_list[i];
> -
> -             if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
> -                     continue;
> -
> -             if (!deve->se_lun) {
> +     rbtree_postorder_for_each_entry_safe(deve, _tmp, &nacl->rb_device_list, 
> rb_node) {
> +             if (deve->se_lun) {
> +                     core_disable_device_list_for_node(deve->se_lun, deve,
> +                             TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
> +             } else {
>                       pr_err("%s device entries device pointer is"
>                               " NULL, but Initiator has access.\n",
>                               tpg->se_tpg_tfo->get_fabric_name());
> -                     continue;
>               }
> -             lun = deve->se_lun;
> -
> -             spin_unlock_irq(&nacl->device_list_lock);
> -             core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
> -                     TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
> -             spin_lock_irq(&nacl->device_list_lock);
>       }
>       spin_unlock_irq(&nacl->device_list_lock);
> -
> -     array_free(nacl->device_list, TRANSPORT_MAX_LUNS_PER_TPG);
> -     nacl->device_list = NULL;
> -
> -     return 0;
>  }
>  
>  void core_update_device_list_access(
> @@ -281,13 +304,15 @@ void core_update_device_list_access(
>       struct se_dev_entry *deve;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[mapped_lun];
> -     if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
> -             deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
> -             deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
> -     } else {
> -             deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_WRITE;
> -             deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
> +     deve = transport_search_deve(nacl, mapped_lun);
> +     if (deve) {
> +             if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
> +                     deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
> +                     deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
> +             } else {
> +                     deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_WRITE;
> +                     deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
> +             }
>       }
>       spin_unlock_irq(&nacl->device_list_lock);
>  }
> @@ -305,18 +330,30 @@ int core_enable_device_list_for_node(
>       struct se_portal_group *tpg)
>  {
>       struct se_port *port = lun->lun_sep;
> -     struct se_dev_entry *deve;
> +     struct se_dev_entry *deve, *new_deve;
>  
> -     spin_lock_irq(&nacl->device_list_lock);
> +     new_deve = kzalloc(sizeof(*deve), GFP_KERNEL);
> +     if (!new_deve)
> +             return -ENOMEM;
>  
> -     deve = nacl->device_list[mapped_lun];
> +     atomic_set(&new_deve->ua_count, 0);
> +     kref_init(&new_deve->refcount);
> +     spin_lock_init(&new_deve->ua_lock);
> +     INIT_LIST_HEAD(&new_deve->alua_port_node);
> +     INIT_LIST_HEAD(&new_deve->ua_list);
> +     new_deve->se_lun = lun;
> +     new_deve->se_lun_acl = lun_acl;
> +     new_deve->mapped_lun = mapped_lun;
>  
> +     spin_lock_irq(&nacl->device_list_lock);
>       /*
>        * Check if the call is handling demo mode -> explicit LUN ACL
>        * transition.  This transition must be for the same struct se_lun
>        * + mapped_lun that was setup in demo mode..
>        */
> -     if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
> +     deve = transport_search_deve(nacl, mapped_lun);
> +     if (deve) {
> +             kfree(new_deve);
>               if (deve->se_lun_acl != NULL) {
>                       pr_err("struct se_dev_entry->se_lun_acl"
>                              " already set for demo mode -> explicit"
> @@ -345,25 +382,24 @@ int core_enable_device_list_for_node(
>               return 0;
>       }
>  
> -     deve->se_lun = lun;
> -     deve->se_lun_acl = lun_acl;
> -     deve->mapped_lun = mapped_lun;
> -     deve->lun_flags |= TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
> -
> -     if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
> -             deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
> -             deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
> -     } else {
> -             deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_WRITE;
> -             deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
> +     if (!transport_insert_deve(nacl, new_deve)) {
> +             pr_err("Could not insert new deve for lun %d\n", mapped_lun);
> +             kfree(new_deve);
> +             spin_unlock_irq(&nacl->device_list_lock);
> +             return -EINVAL;
>       }
>  
> -     deve->creation_time = get_jiffies_64();
> -     deve->attach_count++;
> +     if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE)
> +             new_deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
> +     else
> +             new_deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
> +
> +     new_deve->creation_time = get_jiffies_64();
> +     new_deve->attach_count++;
>       spin_unlock_irq(&nacl->device_list_lock);
>  
>       spin_lock_bh(&port->sep_alua_lock);
> -     list_add_tail(&deve->alua_port_node, &port->sep_alua_list);
> +     list_add_tail(&new_deve->alua_port_node, &port->sep_alua_list);
>       spin_unlock_bh(&port->sep_alua_lock);
>  
>       return 0;
> @@ -371,18 +407,16 @@ int core_enable_device_list_for_node(
>  
>  /*      core_disable_device_list_for_node():
>   *
> - *
> + *   CALLED WITH device_list_lock HELD
>   */
> -int core_disable_device_list_for_node(
> +void core_disable_device_list_for_node(
>       struct se_lun *lun,
> -     struct se_lun_acl *lun_acl,
> -     u32 mapped_lun,
> +     struct se_dev_entry *deve,
>       u32 lun_access,
>       struct se_node_acl *nacl,
>       struct se_portal_group *tpg)
>  {
>       struct se_port *port = lun->lun_sep;
> -     struct se_dev_entry *deve = nacl->device_list[mapped_lun];
>  
>       /*
>        * If the MappedLUN entry is being disabled, the entry in
> @@ -397,11 +431,10 @@ int core_disable_device_list_for_node(
>        * NodeACL context specific PR metadata for demo-mode
>        * MappedLUN *deve will be released below..
>        */
> -     spin_lock_bh(&port->sep_alua_lock);
> +     spin_lock(&port->sep_alua_lock);
>       list_del(&deve->alua_port_node);
> -     spin_unlock_bh(&port->sep_alua_lock);
> +     spin_unlock(&port->sep_alua_lock);
>  
> -     spin_lock_irq(&nacl->device_list_lock);
>       /*
>        * Disable struct se_dev_entry LUN ACL mapping
>        */
> @@ -411,13 +444,12 @@ int core_disable_device_list_for_node(
>       deve->lun_flags = 0;
>       deve->creation_time = 0;
>       deve->attach_count--;
> -     spin_unlock_irq(&nacl->device_list_lock);
>  
>       core_scsi3_free_pr_reg_from_nacl(lun->lun_se_dev, nacl);
>  
> -     put_deve(deve);
> +     rb_erase(&deve->rb_node, &nacl->rb_device_list);
>  
> -     return 0;
> +     put_deve(deve);
>  }
>  
>  /*      core_clear_lun_from_tpg():
> @@ -427,25 +459,17 @@ int core_disable_device_list_for_node(
>  void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
>  {
>       struct se_node_acl *nacl;
> -     struct se_dev_entry *deve;
> -     u32 i;
> +     struct se_dev_entry *deve, *_tmp;
>  
>       spin_lock_irq(&tpg->acl_node_lock);
>       list_for_each_entry(nacl, &tpg->acl_node_list, acl_node) {
>               spin_unlock_irq(&tpg->acl_node_lock);
>  
>               spin_lock_irq(&nacl->device_list_lock);
> -             for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -                     deve = nacl->device_list[i];
> -                     if (lun != deve->se_lun)
> -                             continue;
> -                     spin_unlock_irq(&nacl->device_list_lock);
> -
> -                     core_disable_device_list_for_node(lun, NULL,
> -                             deve->mapped_lun, TRANSPORT_LUNFLAGS_NO_ACCESS,
> -                             nacl, tpg);
> -
> -                     spin_lock_irq(&nacl->device_list_lock);
> +             rbtree_postorder_for_each_entry_safe(deve, _tmp, 
> &nacl->rb_device_list, rb_node) {
> +                     if (lun == deve->se_lun)
> +                             core_disable_device_list_for_node(lun, deve,
> +                                     TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, 
> tpg);
>               }
>               spin_unlock_irq(&nacl->device_list_lock);
>  
> @@ -1301,16 +1325,17 @@ int core_dev_add_initiator_node_lun_acl(
>   *
>   *
>   */
> -int core_dev_del_initiator_node_lun_acl(
> +void core_dev_del_initiator_node_lun_acl(
>       struct se_portal_group *tpg,
>       struct se_lun *lun,
> -     struct se_lun_acl *lacl)
> +     struct se_lun_acl *lacl,
> +     struct se_dev_entry *deve)
>  {
>       struct se_node_acl *nacl;
>  
>       nacl = lacl->se_lun_nacl;
>       if (!nacl)
> -             return -EINVAL;
> +             return;
>  
>       spin_lock(&lun->lun_acl_lock);
>       list_del(&lacl->lacl_list);
> @@ -1318,8 +1343,10 @@ int core_dev_del_initiator_node_lun_acl(
>       smp_mb__after_atomic_dec();
>       spin_unlock(&lun->lun_acl_lock);
>  
> -     core_disable_device_list_for_node(lun, NULL, lacl->mapped_lun,
> +     spin_lock_irq(&nacl->device_list_lock);
> +     core_disable_device_list_for_node(lun, deve,
>               TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
> +     spin_unlock_irq(&nacl->device_list_lock);
>  
>       lacl->se_lun = NULL;
>  
> @@ -1328,8 +1355,6 @@ int core_dev_del_initiator_node_lun_acl(
>               tpg->se_tpg_tfo->get_fabric_name(),
>               tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
>               lacl->initiatorname, lacl->mapped_lun);
> -
> -     return 0;
>  }
>  
>  void core_dev_free_initiator_node_lun_acl(
> diff --git a/drivers/target/target_core_fabric_configfs.c 
> b/drivers/target/target_core_fabric_configfs.c
> index 64cc4dc..eaaed43 100644
> --- a/drivers/target/target_core_fabric_configfs.c
> +++ b/drivers/target/target_core_fabric_configfs.c
> @@ -112,8 +112,8 @@ static int target_fabric_mappedlun_link(
>        * tpg_1/attrib/demo_mode_write_protect=1
>        */
>       spin_lock_irq(&lacl->se_lun_nacl->device_list_lock);
> -     deve = lacl->se_lun_nacl->device_list[lacl->mapped_lun];
> -     if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)
> +     deve = transport_search_deve(lacl->se_lun_nacl, lacl->mapped_lun);
> +     if (deve)
>               lun_access = deve->lun_flags;
>       else
>               lun_access =
> @@ -140,19 +140,20 @@ static int target_fabric_mappedlun_unlink(
>       struct se_lun *lun;
>       struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
>                       struct se_lun_acl, se_lun_group);
> -     struct se_node_acl *nacl = lacl->se_lun_nacl;
> -     struct se_dev_entry *deve = nacl->device_list[lacl->mapped_lun];
> +     struct se_dev_entry *deve;
>       struct se_portal_group *se_tpg;
> +
>       /*
>        * Determine if the underlying MappedLUN has already been released..
>        */
> -     if (!deve->se_lun)
> +     deve = transport_search_deve(lacl->se_lun_nacl, lacl->mapped_lun);
> +     if (!(deve && deve->se_lun))
>               return 0;
>  
>       lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group);
>       se_tpg = lun->lun_sep->sep_tpg;
>  
> -     core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl);
> +     core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl, deve);
>       return 0;
>  }
>  
> @@ -169,13 +170,14 @@ static ssize_t 
> target_fabric_mappedlun_show_write_protect(
>  {
>       struct se_node_acl *se_nacl = lacl->se_lun_nacl;
>       struct se_dev_entry *deve;
> -     ssize_t len;
> +     ssize_t len = 0;
>  
>       spin_lock_irq(&se_nacl->device_list_lock);
> -     deve = se_nacl->device_list[lacl->mapped_lun];
> -     len = sprintf(page, "%d\n",
> -                     (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ?
> -                     1 : 0);
> +     deve = transport_search_deve(se_nacl, lacl->mapped_lun);
> +     if (deve)
> +             len = sprintf(page, "%d\n",
> +                           (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ?
> +                           1 : 0);
>       spin_unlock_irq(&se_nacl->device_list_lock);
>  
>       return len;
> diff --git a/drivers/target/target_core_internal.h 
> b/drivers/target/target_core_internal.h
> index 5d1e4ec..3803dd8 100644
> --- a/drivers/target/target_core_internal.h
> +++ b/drivers/target/target_core_internal.h
> @@ -5,14 +5,16 @@
>  extern struct t10_alua_lu_gp *default_lu_gp;
>  
>  /* target_core_device.c */
> +bool transport_insert_deve(struct se_node_acl *nacl, struct se_dev_entry 
> *deve);
> +struct se_dev_entry *transport_search_deve(struct se_node_acl *nacl, u32 
> mapped_lun);
>  struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
> -int  core_free_device_list_for_node(struct se_node_acl *,
> +void core_free_device_list_for_node(struct se_node_acl *,
>               struct se_portal_group *);
>  void core_update_device_list_access(u32, u32, struct se_node_acl *);
>  int  core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
>               u32, u32, struct se_node_acl *, struct se_portal_group *);
> -int  core_disable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
> -             u32, u32, struct se_node_acl *, struct se_portal_group *);
> +void core_disable_device_list_for_node(struct se_lun *, struct se_dev_entry 
> *,
> +             u32, struct se_node_acl *, struct se_portal_group *);
>  void core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
>  int  core_dev_export(struct se_device *, struct se_portal_group *,
>               struct se_lun *);
> @@ -50,8 +52,8 @@ struct se_lun_acl 
> *core_dev_init_initiator_node_lun_acl(struct se_portal_group *
>               struct se_node_acl *, u32, int *);
>  int  core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
>               struct se_lun_acl *, u32, u32);
> -int  core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
> -             struct se_lun *, struct se_lun_acl *);
> +void core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
> +                                         struct se_lun *, struct se_lun_acl 
> *, struct se_dev_entry*);
>  void core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
>               struct se_lun_acl *lacl);
>  int  core_dev_setup_virtual_lun0(void);
> @@ -98,8 +100,7 @@ static inline void release_deve(struct kref *kref)
>       struct se_dev_entry *deve = container_of(kref,
>                               struct se_dev_entry, refcount);
>  
> -     /* doesn't really get freed because device_list is a static array */
> -     deve->lun_flags &= ~TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
> +     kfree(deve);
>  }
>  
>  #define get_deve(x) kref_get(&x->refcount)
> diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
> index 17a4c3b..0da6696 100644
> --- a/drivers/target/target_core_pr.c
> +++ b/drivers/target/target_core_pr.c
> @@ -322,7 +322,11 @@ static int core_scsi3_pr_seq_non_holder(
>       int legacy = 0; /* Act like a legacy device and return
>                        * RESERVATION CONFLICT on some CDBs */
>  
> -     se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
> +     se_deve = transport_search_deve(se_sess->se_node_acl, cmd->orig_fe_lun);
> +     /* no deve means no conflict */
> +     if (!se_deve)
> +             return 0;
> +
>       /*
>        * Determine if the registration should be ignored due to
>        * non-matching ISIDs in target_scsi3_pr_reservation_check().
> @@ -950,7 +954,11 @@ int core_scsi3_check_aptpl_registration(
>       struct se_lun_acl *lun_acl)
>  {
>       struct se_node_acl *nacl = lun_acl->se_lun_nacl;
> -     struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun];
> +     struct se_dev_entry *deve;
> +
> +     deve = transport_search_deve(nacl, lun_acl->mapped_lun);
> +     if (!deve)
> +             return 0;
>  
>       if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
>               return 0;
> @@ -1424,7 +1432,10 @@ core_scsi3_decode_spec_i_port(
>  
>       memset(dest_iport, 0, 64);
>  
> -     local_se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
> +     local_se_deve = transport_search_deve(se_sess->se_node_acl, 
> cmd->orig_fe_lun);
> +     if (!local_se_deve)
> +             return 0;
> +
>       /*
>        * Allocate a struct pr_transport_id_holder and setup the
>        * local_node_acl and local_se_deve pointers and add to
> @@ -1988,7 +1999,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 
> res_key, u64 sa_res_key,
>               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
>       }
>       se_tpg = se_sess->se_tpg;
> -     se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
>  
>       if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
>               memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
> @@ -2013,6 +2023,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, 
> u64 res_key, u64 sa_res_key,
>                       return 0;
>  
>               if (!spec_i_pt) {
> +
> +                     se_deve = transport_search_deve(se_sess->se_node_acl, 
> cmd->orig_fe_lun);
> +                     if (!se_deve) {
> +                             pr_err("se_deve not found\n");
> +                             return TCM_INVALID_PARAMETER_LIST;
> +                     }
> +
>                       /*
>                        * Perform the Service Action REGISTER on the Initiator
>                        * Port Endpoint that the PRO was received from on the
> diff --git a/drivers/target/target_core_spc.c 
> b/drivers/target/target_core_spc.c
> index 8f52974..0b678fc 100644
> --- a/drivers/target/target_core_spc.c
> +++ b/drivers/target/target_core_spc.c
> @@ -1124,10 +1124,10 @@ static sense_reason_t 
> spc_emulate_request_sense(struct se_cmd *cmd)
>  
>  sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
>  {
> -     struct se_dev_entry *deve;
>       struct se_session *sess = cmd->se_sess;
>       unsigned char *buf;
> -     u32 lun_count = 0, offset = 8, i;
> +     u32 lun_count = 0, offset = 8;
> +     struct rb_node *node;
>  
>       if (cmd->data_length < 16) {
>               pr_warn("REPORT LUNS allocation length %u too small\n",
> @@ -1151,10 +1151,9 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd 
> *cmd)
>       }
>  
>       spin_lock_irq(&sess->se_node_acl->device_list_lock);
> -     for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -             deve = sess->se_node_acl->device_list[i];
> -             if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
> -                     continue;
> +     for (node = rb_first(&sess->se_node_acl->rb_device_list); node; node = 
> rb_next(node)) {
> +             struct se_dev_entry *deve = container_of(node, struct 
> se_dev_entry, rb_node);
> +
>               /*
>                * We determine the correct LUN LIST LENGTH even once we
>                * have reached the initial allocation length.
> diff --git a/drivers/target/target_core_stat.c 
> b/drivers/target/target_core_stat.c
> index 0353899..ef03d51 100644
> --- a/drivers/target/target_core_stat.c
> +++ b/drivers/target/target_core_stat.c
> @@ -1086,8 +1086,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_inst(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1111,8 +1111,8 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1135,8 +1135,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_port(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1158,8 +1158,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_indx(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1180,8 +1180,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_dev_or_port(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1202,8 +1202,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_intr_name(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1224,8 +1224,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_map_indx(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1246,8 +1246,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_att_count(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1268,8 +1268,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_num_cmds(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1290,8 +1290,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_read_mbytes(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1312,8 +1312,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_write_mbytes(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1334,8 +1334,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1356,8 +1356,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_creation_time(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1379,8 +1379,8 @@ static ssize_t 
> target_stat_scsi_auth_intr_show_attr_row_status(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1452,8 +1452,8 @@ static ssize_t 
> target_stat_scsi_att_intr_port_show_attr_inst(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1477,8 +1477,8 @@ static ssize_t 
> target_stat_scsi_att_intr_port_show_attr_dev(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1501,8 +1501,8 @@ static ssize_t 
> target_stat_scsi_att_intr_port_show_attr_port(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> @@ -1550,8 +1550,8 @@ static ssize_t 
> target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
>       ssize_t ret;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[lacl->mapped_lun];
> -     if (!deve->se_lun || !deve->se_lun_acl) {
> +     deve = transport_search_deve(nacl, lacl->mapped_lun);
> +     if (!deve || !deve->se_lun || !deve->se_lun_acl) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -ENODEV;
>       }
> diff --git a/drivers/target/target_core_tpg.c 
> b/drivers/target/target_core_tpg.c
> index e6f9dfb..3efa7c1 100644
> --- a/drivers/target/target_core_tpg.c
> +++ b/drivers/target/target_core_tpg.c
> @@ -54,17 +54,11 @@ static void core_clear_initiator_node_from_tpg(
>       struct se_node_acl *nacl,
>       struct se_portal_group *tpg)
>  {
> -     int i;
> -     struct se_dev_entry *deve;
>       struct se_lun *lun;
> +     struct se_dev_entry *deve, *_tmp;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -             deve = nacl->device_list[i];
> -
> -             if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
> -                     continue;
> -
> +     rbtree_postorder_for_each_entry_safe(deve, _tmp, &nacl->rb_device_list, 
> rb_node) {
>               if (!deve->se_lun) {
>                       pr_err("%s device entries device pointer is"
>                               " NULL, but Initiator has access.\n",
> @@ -73,11 +67,8 @@ static void core_clear_initiator_node_from_tpg(
>               }
>  
>               lun = deve->se_lun;
> -             spin_unlock_irq(&nacl->device_list_lock);
> -             core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
> +             core_disable_device_list_for_node(lun, deve,
>                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
> -
> -             spin_lock_irq(&nacl->device_list_lock);
>       }
>       spin_unlock_irq(&nacl->device_list_lock);
>  }
> @@ -217,34 +208,6 @@ static void *array_zalloc(int n, size_t size, gfp_t 
> flags)
>       return a;
>  }
>  
> -/*      core_create_device_list_for_node():
> - *
> - *
> - */
> -static int core_create_device_list_for_node(struct se_node_acl *nacl)
> -{
> -     struct se_dev_entry *deve;
> -     int i;
> -
> -     nacl->device_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG,
> -                     sizeof(struct se_dev_entry), GFP_KERNEL);
> -     if (!nacl->device_list) {
> -             pr_err("Unable to allocate memory for"
> -                     " struct se_node_acl->device_list\n");
> -             return -ENOMEM;
> -     }
> -     for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
> -             deve = nacl->device_list[i];
> -
> -             atomic_set(&deve->ua_count, 0);
> -             kref_init(&deve->refcount);
> -             spin_lock_init(&deve->ua_lock);
> -             INIT_LIST_HEAD(&deve->alua_port_node);
> -             INIT_LIST_HEAD(&deve->ua_list);
> -     }
> -
> -     return 0;
> -}
>  
>  /*   core_tpg_check_initiator_node_acl()
>   *
> @@ -283,10 +246,7 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
>  
>       tpg->se_tpg_tfo->set_default_node_attributes(acl);
>  
> -     if (core_create_device_list_for_node(acl) < 0) {
> -             tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
> -             return NULL;
> -     }
> +     acl->rb_device_list = RB_ROOT;
>  
>       if (core_set_queue_depth_for_node(tpg, acl) < 0) {
>               core_free_device_list_for_node(acl, tpg);
> @@ -410,10 +370,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
>  
>       tpg->se_tpg_tfo->set_default_node_attributes(acl);
>  
> -     if (core_create_device_list_for_node(acl) < 0) {
> -             tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
> -             return ERR_PTR(-ENOMEM);
> -     }
> +     acl->rb_device_list = RB_ROOT;
>  
>       if (core_set_queue_depth_for_node(tpg, acl) < 0) {
>               core_free_device_list_for_node(acl, tpg);
> diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c
> index 2a1cbf9..5260442 100644
> --- a/drivers/target/target_core_ua.c
> +++ b/drivers/target/target_core_ua.c
> @@ -51,8 +51,8 @@ target_scsi3_ua_check(struct se_cmd *cmd)
>       if (!nacl)
>               return 0;
>  
> -     deve = nacl->device_list[cmd->orig_fe_lun];
> -     if (!atomic_read(&deve->ua_count))
> +     deve = transport_search_deve(nacl, cmd->orig_fe_lun);
> +     if (!deve || !atomic_read(&deve->ua_count))
>               return 0;
>       /*
>        * From sam4r14, section 5.14 Unit attention condition:
> @@ -105,7 +105,11 @@ int core_scsi3_ua_allocate(
>       ua->ua_ascq = ascq;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[unpacked_lun];
> +     deve = transport_search_deve(nacl, unpacked_lun);
> +     if (!deve) {
> +             spin_unlock_irq(&nacl->device_list_lock);
> +             return 0;
> +     }
>  
>       spin_lock(&deve->ua_lock);
>       list_for_each_entry_safe(ua_p, ua_tmp, &deve->ua_list, ua_nacl_node) {
> @@ -215,8 +219,8 @@ void core_scsi3_ua_for_check_condition(
>               return;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[cmd->orig_fe_lun];
> -     if (!atomic_read(&deve->ua_count)) {
> +     deve = transport_search_deve(nacl, cmd->orig_fe_lun);
> +     if (!deve || !atomic_read(&deve->ua_count)) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return;
>       }
> @@ -284,8 +288,8 @@ int core_scsi3_ua_clear_for_request_sense(
>               return -EINVAL;
>  
>       spin_lock_irq(&nacl->device_list_lock);
> -     deve = nacl->device_list[cmd->orig_fe_lun];
> -     if (!atomic_read(&deve->ua_count)) {
> +     deve = transport_search_deve(nacl, cmd->orig_fe_lun);
> +     if (!deve || !atomic_read(&deve->ua_count)) {
>               spin_unlock_irq(&nacl->device_list_lock);
>               return -EPERM;
>       }
> diff --git a/include/target/target_core_base.h 
> b/include/target/target_core_base.h
> index 513429a..3f54fee 100644
> --- a/include/target/target_core_base.h
> +++ b/include/target/target_core_base.h
> @@ -171,9 +171,8 @@ enum se_cmd_flags_table {
>  /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
>  enum transport_lunflags_table {
>       TRANSPORT_LUNFLAGS_NO_ACCESS            = 0x00,
> -     TRANSPORT_LUNFLAGS_INITIATOR_ACCESS     = 0x01,
> -     TRANSPORT_LUNFLAGS_READ_ONLY            = 0x02,
> -     TRANSPORT_LUNFLAGS_READ_WRITE           = 0x04,
> +     TRANSPORT_LUNFLAGS_READ_ONLY            = 0x01,
> +     TRANSPORT_LUNFLAGS_READ_WRITE           = 0x02,
>  };
>  
>  /*
> @@ -522,7 +521,7 @@ struct se_node_acl {
>       spinlock_t              stats_lock;
>       /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
>       atomic_t                acl_pr_ref_count;
> -     struct se_dev_entry     **device_list;
> +     struct rb_root          rb_device_list;
>       struct se_session       *nacl_sess;
>       struct se_portal_group *se_tpg;
>       spinlock_t              device_list_lock;
> @@ -576,6 +575,7 @@ struct se_lun_acl {
>  };
>  
>  struct se_dev_entry {
> +     struct rb_node          rb_node;
>       bool                    def_pr_registered;
>       /* See transport_lunflags_table */
>       u32                     lun_flags;


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to