aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorNeerav Parikh <Neerav.Parikh@intel.com>2011-05-16 19:45:29 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-24 12:36:29 -0400
commitbdf252183e58654fcceedbf3fdcfd878b9e4f2d6 (patch)
treeb02db1a5baab6cde3fb77f2e9c7c1c302e996ce1 /drivers/scsi/fcoe
parentc051ad2e57e379e07e4ec28b2a54eeb0d04c5d59 (diff)
[SCSI] fcoe: Prevent creation of an NPIV port with duplicate WWPN
This patch adds a validation step before allowing creation of a new NPIV port. It checks whether the WWPN passed for the new NPIV port to be created is unique for the given physical port. Signed-off-by: Neerav Parikh <Neerav.Parikh@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r--drivers/scsi/fcoe/fcoe.c58
-rw-r--r--drivers/scsi/fcoe/fcoe.h10
2 files changed, 68 insertions, 0 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index cc23bd9480b2..155d7b9bdeae 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -137,6 +137,7 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled);
137static int fcoe_vport_disable(struct fc_vport *, bool disable); 137static int fcoe_vport_disable(struct fc_vport *, bool disable);
138static void fcoe_set_vport_symbolic_name(struct fc_vport *); 138static void fcoe_set_vport_symbolic_name(struct fc_vport *);
139static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); 139static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
140static int fcoe_validate_vport_create(struct fc_vport *);
140 141
141static struct libfc_function_template fcoe_libfc_fcn_templ = { 142static struct libfc_function_template fcoe_libfc_fcn_templ = {
142 .frame_send = fcoe_xmit, 143 .frame_send = fcoe_xmit,
@@ -2351,6 +2352,17 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
2351 struct fcoe_interface *fcoe = port->priv; 2352 struct fcoe_interface *fcoe = port->priv;
2352 struct net_device *netdev = fcoe->netdev; 2353 struct net_device *netdev = fcoe->netdev;
2353 struct fc_lport *vn_port; 2354 struct fc_lport *vn_port;
2355 int rc;
2356 char buf[32];
2357
2358 rc = fcoe_validate_vport_create(vport);
2359 if (rc) {
2360 wwn_to_str(vport->port_name, buf, sizeof(buf));
2361 printk(KERN_ERR "fcoe: Failed to create vport, "
2362 "WWPN (0x%s) already exists\n",
2363 buf);
2364 return rc;
2365 }
2354 2366
2355 mutex_lock(&fcoe_config_mutex); 2367 mutex_lock(&fcoe_config_mutex);
2356 vn_port = fcoe_if_create(fcoe, &vport->dev, 1); 2368 vn_port = fcoe_if_create(fcoe, &vport->dev, 1);
@@ -2497,3 +2509,49 @@ static void fcoe_set_port_id(struct fc_lport *lport,
2497 if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) 2509 if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
2498 fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); 2510 fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
2499} 2511}
2512
2513/**
2514 * fcoe_validate_vport_create() - Validate a vport before creating it
2515 * @vport: NPIV port to be created
2516 *
2517 * This routine is meant to add validation for a vport before creating it
2518 * via fcoe_vport_create().
2519 * Current validations are:
2520 * - WWPN supplied is unique for given lport
2521 *
2522 *
2523*/
2524static int fcoe_validate_vport_create(struct fc_vport *vport)
2525{
2526 struct Scsi_Host *shost = vport_to_shost(vport);
2527 struct fc_lport *n_port = shost_priv(shost);
2528 struct fc_lport *vn_port;
2529 int rc = 0;
2530 char buf[32];
2531
2532 mutex_lock(&n_port->lp_mutex);
2533
2534 wwn_to_str(vport->port_name, buf, sizeof(buf));
2535 /* Check if the wwpn is not same as that of the lport */
2536 if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
2537 FCOE_DBG("vport WWPN 0x%s is same as that of the "
2538 "base port WWPN\n", buf);
2539 rc = -EINVAL;
2540 goto out;
2541 }
2542
2543 /* Check if there is any existing vport with same wwpn */
2544 list_for_each_entry(vn_port, &n_port->vports, list) {
2545 if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
2546 FCOE_DBG("vport with given WWPN 0x%s already "
2547 "exists\n", buf);
2548 rc = -EINVAL;
2549 break;
2550 }
2551 }
2552
2553out:
2554 mutex_unlock(&n_port->lp_mutex);
2555
2556 return rc;
2557}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 408a6fd78fb4..c4a93993c0cf 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -99,4 +99,14 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
99 ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; 99 ((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
100} 100}
101 101
102static inline void wwn_to_str(u64 wwn, char *buf, int len)
103{
104 u8 wwpn[8];
105
106 u64_to_wwn(wwn, wwpn);
107 snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
108 wwpn[0], wwpn[1], wwpn[2], wwpn[3],
109 wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
110}
111
102#endif /* _FCOE_H_ */ 112#endif /* _FCOE_H_ */