[SCSI] bfa: Implement LUN Masking feature using the SCSI Slave Callouts.
This patch re-implements LUN Masking feature using SCSI Slave Callouts. With the new design in the slave_alloc entry point; for each new LUN discovered we check with our internal LUN Masking config whether to expose or to mask this particular LUN. We return -ENXIO (No such device or address) from slave_alloc for the LUNs we don't want to be exposed. We also notify the SCSI mid-layer to do a sequential LUN scan rather than REPORT_LUNS based scan if LUN masking is enabled on our HBA port, since a -ENXIO from any LUN in REPORT_LUNS based scan translates to a scan abort. This patch also handles the dynamic lun masking config change from enable to disable or vice-versa by resetting sdev_bflags of LUN 0 appropriately. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
8ca2dd87e7
commit
5b7db7af52
|
@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
|
|||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcs_vport_start(&vport->fcs_vport);
|
||||
list_add_tail(&vport->list_entry, &bfad->vport_list);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
|
@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
bfad->ref_count = 0;
|
||||
bfad->pport.bfad = bfad;
|
||||
INIT_LIST_HEAD(&bfad->pbc_vport_list);
|
||||
INIT_LIST_HEAD(&bfad->vport_list);
|
||||
|
||||
/* Setup the debugfs node for this bfad */
|
||||
if (bfa_debugfs_enable)
|
||||
|
|
|
@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
|
|||
|
||||
free_scsi_host:
|
||||
bfad_scsi_host_free(bfad, im_port);
|
||||
|
||||
list_del(&vport->list_entry);
|
||||
kfree(vport);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2394,6 +2394,21 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Function to reset the LUN SCAN mode */
|
||||
static void
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg)
|
||||
{
|
||||
struct bfad_im_port_s *pport_im = bfad->pport.im_port;
|
||||
struct bfad_vport_s *vport = NULL;
|
||||
|
||||
/* Set the scsi device LUN SCAN flags for base port */
|
||||
bfad_reset_sdev_bflags(pport_im, lunmask_cfg);
|
||||
|
||||
/* Set the scsi device LUN SCAN flags for the vports */
|
||||
list_for_each_entry(vport, &bfad->vport_list, list_entry)
|
||||
bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg);
|
||||
}
|
||||
|
||||
int
|
||||
bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
|
||||
{
|
||||
|
@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE)
|
||||
if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) {
|
||||
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE);
|
||||
else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE)
|
||||
/* Set the LUN Scanning mode to be Sequential scan */
|
||||
if (iocmd->status == BFA_STATUS_OK)
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE);
|
||||
} else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) {
|
||||
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE);
|
||||
else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
|
||||
/* Set the LUN Scanning mode to default REPORT_LUNS scan */
|
||||
if (iocmd->status == BFA_STATUS_OK)
|
||||
bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE);
|
||||
} else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
|
||||
iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
return 0;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_bsg_fc.h>
|
||||
#include <scsi/scsi_devinfo.h>
|
||||
|
||||
#include "bfa_modules.h"
|
||||
#include "bfa_fcs.h"
|
||||
|
@ -227,6 +228,7 @@ struct bfad_s {
|
|||
struct list_head active_aen_q;
|
||||
struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY];
|
||||
spinlock_t bfad_aen_spinlock;
|
||||
struct list_head vport_list;
|
||||
};
|
||||
|
||||
/* BFAD state machine events */
|
||||
|
|
|
@ -917,6 +917,37 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function is invoked from the SCSI Host Template slave_alloc() entry point.
|
||||
* Has the logic to query the LUN Mask database to check if this LUN needs to
|
||||
* be made visible to the SCSI mid-layer or not.
|
||||
*
|
||||
* Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack.
|
||||
* Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack.
|
||||
*/
|
||||
static int
|
||||
bfad_im_check_if_make_lun_visible(struct scsi_device *sdev,
|
||||
struct fc_rport *rport)
|
||||
{
|
||||
struct bfad_itnim_data_s *itnim_data =
|
||||
(struct bfad_itnim_data_s *) rport->dd_data;
|
||||
struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
|
||||
struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport;
|
||||
struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa);
|
||||
int i = 0, ret = -ENXIO;
|
||||
|
||||
for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
|
||||
if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE &&
|
||||
scsilun_to_int(&lun_list[i].lun) == sdev->lun &&
|
||||
lun_list[i].rp_tag == bfa_rport->rport_tag &&
|
||||
lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) {
|
||||
ret = BFA_STATUS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scsi_Host template entry slave_alloc
|
||||
*/
|
||||
|
@ -924,10 +955,33 @@ static int
|
|||
bfad_im_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
|
||||
struct bfad_itnim_data_s *itnim_data =
|
||||
(struct bfad_itnim_data_s *) rport->dd_data;
|
||||
struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
|
||||
|
||||
if (!rport || fc_remote_port_chkready(rport))
|
||||
return -ENXIO;
|
||||
|
||||
if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
|
||||
/*
|
||||
* We should not mask LUN 0 - since this will translate
|
||||
* to no LUN / TARGET for SCSI ml resulting no scan.
|
||||
*/
|
||||
if (sdev->lun == 0) {
|
||||
sdev->sdev_bflags |= BLIST_NOREPORTLUN |
|
||||
BLIST_SPARSELUN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query LUN Mask configuration - to expose this LUN
|
||||
* to the SCSI mid-layer or to mask it.
|
||||
*/
|
||||
if (bfad_im_check_if_make_lun_visible(sdev, rport) !=
|
||||
BFA_STATUS_OK)
|
||||
return -ENXIO;
|
||||
}
|
||||
done:
|
||||
sdev->hostdata = rport->dd_data;
|
||||
|
||||
return 0;
|
||||
|
@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
|
|||
&& (fc_rport->scsi_target_id < MAX_FCP_TARGET))
|
||||
itnim->scsi_tgt_id = fc_rport->scsi_target_id;
|
||||
|
||||
itnim->channel = fc_rport->channel;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ struct bfad_itnim_s {
|
|||
struct fc_rport *fc_rport;
|
||||
struct bfa_itnim_s *bfa_itnim;
|
||||
u16 scsi_tgt_id;
|
||||
u16 channel;
|
||||
u16 queue_work;
|
||||
unsigned long last_ramp_up_time;
|
||||
unsigned long last_queue_full_time;
|
||||
|
@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id);
|
|||
int bfad_im_bsg_request(struct fc_bsg_job *job);
|
||||
int bfad_im_bsg_timeout(struct fc_bsg_job *job);
|
||||
|
||||
/*
|
||||
* Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the
|
||||
* SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan
|
||||
*
|
||||
* Internally iterate's over all the ITNIM's part of the im_port & set's the
|
||||
* sdev_bflags for the scsi_device associated with LUN #0.
|
||||
*/
|
||||
#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do { \
|
||||
struct scsi_device *__sdev = NULL; \
|
||||
struct bfad_itnim_s *__itnim = NULL; \
|
||||
u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN; \
|
||||
list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \
|
||||
list_entry) { \
|
||||
__sdev = scsi_device_lookup((__im_port)->shost, \
|
||||
__itnim->channel, \
|
||||
__itnim->scsi_tgt_id, 0); \
|
||||
if (__sdev) { \
|
||||
if ((__lunmask_cfg) == BFA_TRUE) \
|
||||
__sdev->sdev_bflags |= scan_flags; \
|
||||
else \
|
||||
__sdev->sdev_bflags &= ~scan_flags; \
|
||||
scsi_device_put(__sdev); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue