[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:
Krishna Gudipati
2011-12-20 18:58:32 -08:00
committed by James Bottomley
parent 8ca2dd87e7
commit 5b7db7af52
6 changed files with 112 additions and 4 deletions

View File

@@ -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;
}