Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 173618
b: refs/heads/master
c: b4a9c7e
h: refs/heads/master
v: v3
  • Loading branch information
Joe Eykholt authored and James Bottomley committed Dec 4, 2009
1 parent 9b8e2db commit 3295731
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4b53662bd594941e5e5e540baaaff6a3e66d062c
refs/heads/master: b4a9c7ede96e90f7b1ec009ce7256059295e76df
69 changes: 50 additions & 19 deletions trunk/drivers/scsi/libfc/fc_rport.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ static const char *fc_rport_state_names[] = {
[RPORT_ST_LOGO] = "LOGO",
[RPORT_ST_ADISC] = "ADISC",
[RPORT_ST_DELETE] = "Delete",
[RPORT_ST_RESTART] = "Restart",
};

/**
Expand All @@ -99,8 +100,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
struct fc_rport_priv *rdata;

list_for_each_entry(rdata, &lport->disc.rports, peers)
if (rdata->ids.port_id == port_id &&
rdata->rp_state != RPORT_ST_DELETE)
if (rdata->ids.port_id == port_id)
return rdata;
return NULL;
}
Expand Down Expand Up @@ -235,6 +235,7 @@ static void fc_rport_work(struct work_struct *work)
struct fc_rport_operations *rport_ops;
struct fc_rport_identifiers ids;
struct fc_rport *rport;
int restart = 0;

mutex_lock(&rdata->rp_mutex);
event = rdata->event;
Expand Down Expand Up @@ -287,8 +288,19 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);

if (port_id != FC_FID_DIR_SERV) {
/*
* We must drop rp_mutex before taking disc_mutex.
* Re-evaluate state to allow for restart.
* A transition to RESTART state must only happen
* while disc_mutex is held and rdata is on the list.
*/
mutex_lock(&lport->disc.disc_mutex);
list_del(&rdata->peers);
mutex_lock(&rdata->rp_mutex);
if (rdata->rp_state == RPORT_ST_RESTART)
restart = 1;
else
list_del(&rdata->peers);
mutex_unlock(&rdata->rp_mutex);
mutex_unlock(&lport->disc.disc_mutex);
}

Expand All @@ -312,7 +324,13 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);
fc_remote_port_delete(rport);
}
kref_put(&rdata->kref, lport->tt.rport_destroy);
if (restart) {
mutex_lock(&rdata->rp_mutex);
FC_RPORT_DBG(rdata, "work restart\n");
fc_rport_enter_plogi(rdata);
mutex_unlock(&rdata->rp_mutex);
} else
kref_put(&rdata->kref, lport->tt.rport_destroy);
break;

default:
Expand Down Expand Up @@ -342,6 +360,12 @@ int fc_rport_login(struct fc_rport_priv *rdata)
FC_RPORT_DBG(rdata, "ADISC port\n");
fc_rport_enter_adisc(rdata);
break;
case RPORT_ST_RESTART:
break;
case RPORT_ST_DELETE:
FC_RPORT_DBG(rdata, "Restart deleted port\n");
fc_rport_state_enter(rdata, RPORT_ST_RESTART);
break;
default:
FC_RPORT_DBG(rdata, "Login to port\n");
fc_rport_enter_plogi(rdata);
Expand Down Expand Up @@ -397,20 +421,21 @@ int fc_rport_logoff(struct fc_rport_priv *rdata)

if (rdata->rp_state == RPORT_ST_DELETE) {
FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");
mutex_unlock(&rdata->rp_mutex);
goto out;
}

fc_rport_enter_logo(rdata);
if (rdata->rp_state == RPORT_ST_RESTART)
FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n");
else
fc_rport_enter_logo(rdata);

/*
* Change the state to Delete so that we discard
* the response.
*/
fc_rport_enter_delete(rdata, RPORT_EV_STOP);
mutex_unlock(&rdata->rp_mutex);

out:
mutex_unlock(&rdata->rp_mutex);
return 0;
}

Expand Down Expand Up @@ -466,6 +491,7 @@ static void fc_rport_timeout(struct work_struct *work)
case RPORT_ST_READY:
case RPORT_ST_INIT:
case RPORT_ST_DELETE:
case RPORT_ST_RESTART:
break;
}

Expand Down Expand Up @@ -499,6 +525,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
fc_rport_enter_logo(rdata);
break;
case RPORT_ST_DELETE:
case RPORT_ST_RESTART:
case RPORT_ST_READY:
case RPORT_ST_INIT:
break;
Expand Down Expand Up @@ -1248,18 +1275,22 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
}
break;
case RPORT_ST_PRLI:
case RPORT_ST_RTV:
case RPORT_ST_READY:
case RPORT_ST_ADISC:
FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "
"- ignored for now\n", rdata->rp_state);
/* XXX TBD - should reset */
break;
case RPORT_ST_DELETE:
default:
FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n",
rdata->rp_state);
fc_frame_free(rx_fp);
goto out;
case RPORT_ST_LOGO:
case RPORT_ST_RESTART:
FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n",
fc_rport_state(rdata));
mutex_unlock(&rdata->rp_mutex);
rjt_data.reason = ELS_RJT_BUSY;
rjt_data.explan = ELS_EXPL_NONE;
goto reject;
}

/*
Expand Down Expand Up @@ -1510,14 +1541,14 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
fc_rport_state(rdata));

fc_rport_enter_delete(rdata, RPORT_EV_LOGO);

/*
* If the remote port was created due to discovery,
* log back in. It may have seen a stale RSCN about us.
* If the remote port was created due to discovery, set state
* to log back in. It may have seen a stale RSCN about us.
*/
if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id)
fc_rport_enter_plogi(rdata);
else
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
if (rdata->disc_id)
fc_rport_state_enter(rdata, RPORT_ST_RESTART);
mutex_unlock(&rdata->rp_mutex);
} else
FC_RPORT_ID_DBG(lport, sid,
Expand Down
1 change: 1 addition & 0 deletions trunk/include/scsi/libfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ enum fc_rport_state {
RPORT_ST_LOGO, /* port logout sent */
RPORT_ST_ADISC, /* Discover Address sent */
RPORT_ST_DELETE, /* port being deleted */
RPORT_ST_RESTART, /* remote port being deleted and will restart */
};

/**
Expand Down

0 comments on commit 3295731

Please sign in to comment.