Skip to content

Commit

Permalink
[SCSI] libfc: make rport structure optional
Browse files Browse the repository at this point in the history
Allow a struct fc_rport_priv to have no fc_rport associated with it.
This sets up to remove the need for "rogue" rports.

Add a few fields to fc_rport_priv that are needed before the fc_rport
is created.  These are the ids, maxframe_size, classes, and rport pointer.

Remove the macro PRIV_TO_RPORT().  Just use rdata->rport where appropriate.

To take the place of the get_device()/put_device ops that were used to
hold both the rport and rdata, add a reference count to rdata structures
using kref.  When kref_get decrements the refcount to zero, a new template
function releasing the rdata should be called.  This will take care of
freeing the rdata and releasing the hold on the rport (for now).  After
subsequent patches make the rport truly optional, this release function
will simply free the rdata.

Remove the simple inline function fc_rport_set_name(), which becomes
semanticly ambiguous otherwise.  The caller will set the port_name and
node_name in the rdata->Ids, which will later be copied to the rport
when it its created.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Joe Eykholt authored and James Bottomley committed Sep 10, 2009
1 parent a46f327 commit f211fa5
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 101 deletions.
54 changes: 19 additions & 35 deletions drivers/scsi/libfc/fc_disc.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

static void fc_disc_gpn_ft_req(struct fc_disc *);
static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
static int fc_disc_new_target(struct fc_disc *, struct fc_rport *,
static int fc_disc_new_target(struct fc_disc *, struct fc_rport_priv *,
struct fc_rport_identifiers *);
static void fc_disc_done(struct fc_disc *);
static void fc_disc_timeout(struct work_struct *);
Expand All @@ -63,12 +63,10 @@ struct fc_rport_priv *fc_disc_lookup_rport(const struct fc_lport *lport,
u32 port_id)
{
const struct fc_disc *disc = &lport->disc;
struct fc_rport *rport;
struct fc_rport_priv *rdata;

list_for_each_entry(rdata, &disc->rports, peers) {
rport = PRIV_TO_RPORT(rdata);
if (rport->port_id == port_id)
if (rdata->ids.port_id == port_id)
return rdata;
}
return NULL;
Expand Down Expand Up @@ -115,10 +113,9 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
enum fc_rport_event event)
{
struct fc_disc *disc = &lport->disc;
struct fc_rport *rport = PRIV_TO_RPORT(rdata);

FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
rport->port_id);
rdata->ids.port_id);

switch (event) {
case RPORT_EV_CREATED:
Expand Down Expand Up @@ -320,8 +317,6 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
struct fc_lport *lport)
{
struct fc_rport_priv *rdata;
struct fc_rport *rport;
struct fc_rport_identifiers ids;
struct fc_disc *disc = &lport->disc;

/*
Expand Down Expand Up @@ -349,18 +344,12 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
*/
rdata = disc->lport->ptp_rp;
if (rdata) {
rport = PRIV_TO_RPORT(rdata);
ids.port_id = rport->port_id;
ids.port_name = rport->port_name;
ids.node_name = rport->node_name;
ids.roles = FC_RPORT_ROLE_UNKNOWN;
get_device(&rport->dev);

if (!fc_disc_new_target(disc, rport, &ids)) {
kref_get(&rdata->kref);
if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
disc->event = DISC_EV_SUCCESS;
fc_disc_done(disc);
}
put_device(&rport->dev);
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
} else {
fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */
}
Expand All @@ -375,56 +364,51 @@ static struct fc_rport_operations fc_disc_rport_ops = {
/**
* fc_disc_new_target() - Handle new target found by discovery
* @lport: FC local port
* @rport: The previous FC remote port (NULL if new remote port)
* @rdata: The previous FC remote port priv (NULL if new remote port)
* @ids: Identifiers for the new FC remote port
*
* Locking Note: This function expects that the disc_mutex is locked
* before it is called.
*/
static int fc_disc_new_target(struct fc_disc *disc,
struct fc_rport *rport,
struct fc_rport_priv *rdata,
struct fc_rport_identifiers *ids)
{
struct fc_lport *lport = disc->lport;
struct fc_rport_priv *rdata;
int error = 0;

if (rport && ids->port_name) {
if (rport->port_name == -1) {
if (rdata && ids->port_name) {
if (rdata->ids.port_name == -1) {
/*
* Set WWN and fall through to notify of create.
*/
fc_rport_set_name(rport, ids->port_name,
rport->node_name);
} else if (rport->port_name != ids->port_name) {
rdata->ids.port_name = ids->port_name;
rdata->ids.node_name = ids->node_name;
} else if (rdata->ids.port_name != ids->port_name) {
/*
* This is a new port with the same FCID as
* a previously-discovered port. Presumably the old
* port logged out and a new port logged in and was
* assigned the same FCID. This should be rare.
* Delete the old one and fall thru to re-create.
*/
rdata = rport->dd_data;
list_del(&rdata->peers);
lport->tt.rport_logoff(rdata);
rport = NULL;
rdata = NULL;
}
}
if (((ids->port_name != -1) || (ids->port_id != -1)) &&
ids->port_id != fc_host_port_id(lport->host) &&
ids->port_name != lport->wwpn) {
if (!rport) {
if (!rdata) {
rdata = lport->tt.rport_lookup(lport, ids->port_id);
if (!rport) {
if (!rdata) {
rdata = lport->tt.rport_create(lport, ids);
if (!rdata)
error = -ENOMEM;
}
if (!rdata)
error = -ENOMEM;
else
rport = PRIV_TO_RPORT(rdata);
}
if (rport) {
rdata = rport->dd_data;
if (rdata) {
rdata->ops = &fc_disc_rport_ops;
rdata->rp_state = RPORT_ST_INIT;
list_add_tail(&rdata->peers, &disc->rogue_rports);
Expand Down
14 changes: 6 additions & 8 deletions drivers/scsi/libfc/fc_lport.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,12 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
struct fc_rport_priv *rdata,
enum fc_rport_event event)
{
struct fc_rport *rport = PRIV_TO_RPORT(rdata);

FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
rport->port_id);
rdata->ids.port_id);

switch (event) {
case RPORT_EV_CREATED:
if (rport->port_id == FC_FID_DIR_SERV) {
if (rdata->ids.port_id == FC_FID_DIR_SERV) {
mutex_lock(&lport->lp_mutex);
if (lport->state == LPORT_ST_DNS) {
lport->dns_rp = rdata;
Expand All @@ -160,28 +158,28 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
"on port (%6x) for the directory "
"server, but the lport is not "
"in the DNS state, it's in the "
"%d state", rport->port_id,
"%d state", rdata->ids.port_id,
lport->state);
lport->tt.rport_logoff(rdata);
}
mutex_unlock(&lport->lp_mutex);
} else
FC_LPORT_DBG(lport, "Received an event for port (%6x) "
"which is not the directory server\n",
rport->port_id);
rdata->ids.port_id);
break;
case RPORT_EV_LOGO:
case RPORT_EV_FAILED:
case RPORT_EV_STOP:
if (rport->port_id == FC_FID_DIR_SERV) {
if (rdata->ids.port_id == FC_FID_DIR_SERV) {
mutex_lock(&lport->lp_mutex);
lport->dns_rp = NULL;
mutex_unlock(&lport->lp_mutex);

} else
FC_LPORT_DBG(lport, "Received an event for port (%6x) "
"which is not the directory server\n",
rport->port_id);
rdata->ids.port_id);
break;
case RPORT_EV_NONE:
break;
Expand Down
Loading

0 comments on commit f211fa5

Please sign in to comment.