Commit 4062e12b authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: zfcp act enhancements

From: Andreas Herrmann <aherrman@de.ibm.com>
From: Maxim Shchetynin <maxim@de.ibm.com>

zfcp host adapter changes:
 - Add access control enhancements.
 - Add event callbacks.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 18f1b363
......@@ -45,14 +45,6 @@ static int __init zfcp_module_init(void);
static void zfcp_ns_gid_pn_handler(unsigned long);
/* miscellaneous */
static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
void __user *, size_t);
static inline int zfcp_sg_list_copy_to_user(void __user *,
struct zfcp_sg_list *, size_t);
static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
unsigned int, unsigned long);
......@@ -345,8 +337,11 @@ zfcp_module_init(void)
if (zfcp_device_setup(device))
zfcp_init_device_configure();
init_waitqueue_head(&zfcp_callbacks.wq);
goto out;
out_ccw_register:
misc_deregister(&zfcp_cfdc_misc);
out_misc_register:
......@@ -564,7 +559,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
* elements of the scatter-gather list. The maximum size of a single element
* in the scatter-gather list is PAGE_SIZE.
*/
static inline int
int
zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
{
struct scatterlist *sg;
......@@ -612,7 +607,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
* Memory for each element in the scatter-gather list is freed.
* Finally sg_list->sg is freed itself and sg_list->count is reset.
*/
static inline void
void
zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
{
struct scatterlist *sg;
......@@ -657,7 +652,7 @@ zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
* @size: number of bytes to be copied
* Return: 0 on success, -EFAULT if copy_from_user fails.
*/
static inline int
int
zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
void __user *user_buffer,
size_t size)
......@@ -695,7 +690,7 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
* @size: number of bytes to be copied
* Return: 0 on success, -EFAULT if copy_to_user fails
*/
static inline int
int
zfcp_sg_list_copy_to_user(void __user *user_buffer,
struct zfcp_sg_list *sg_list,
size_t size)
......@@ -1423,6 +1418,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
zfcp_adapter_get(adapter);
zfcp_cb_port_add(port);
return port;
}
......@@ -1650,6 +1647,7 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
else
zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
zfcp_cb_incoming_els(adapter, status_buffer->payload);
}
......@@ -1976,4 +1974,161 @@ zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par)
return ret;
}
#undef ZFCP_LOG_AREA
/****************************************************************/
/******* HBA API Support related Functions *********************/
/****************************************************************/
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC
struct zfcp_callbacks zfcp_callbacks = { };
/**
* zfcp_register_callbacks - register callbacks for event handling in HBA API
* @callbacks: set of callback functions to be registered
*/
void
zfcp_register_callbacks(struct zfcp_callbacks *callbacks)
{
zfcp_callbacks.incoming_els = callbacks->incoming_els;
zfcp_callbacks.link_down = callbacks->link_down;
zfcp_callbacks.link_up = callbacks->link_up;
zfcp_callbacks.adapter_add = callbacks->adapter_add;
zfcp_callbacks.port_add = callbacks->port_add;
zfcp_callbacks.unit_add = callbacks->unit_add;
}
/**
* zfcp_unregister_callbacks - deregister callbacks for event handling
*/
void
zfcp_unregister_callbacks(void)
{
zfcp_callbacks.incoming_els = NULL;
zfcp_callbacks.link_down = NULL;
zfcp_callbacks.link_up = NULL;
zfcp_callbacks.adapter_add = NULL;
zfcp_callbacks.port_add = NULL;
zfcp_callbacks.unit_add = NULL;
/* wait until all callbacks returned */
wait_event(zfcp_callbacks.wq,
atomic_read(&zfcp_callbacks.refcount) == 0);
}
/**
* zfcp_cb_incoming_els - make callback for incoming els
* @adpater: adapter where ELS was received
* @payload: received ELS payload
*/
void
zfcp_cb_incoming_els(struct zfcp_adapter *adapter, void *payload)
{
zfcp_cb_incoming_els_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.incoming_els;
if (cb)
cb(adapter, payload);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
/**
* zfcp_cb_link_down - make callback for link down event
* @adapter: adapter where link down occurred
*/
void
zfcp_cb_link_down(struct zfcp_adapter *adapter)
{
zfcp_cb_link_down_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.link_down;
if (cb)
cb(adapter);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
/**
* zfcp_cb_link_up - make callback for link up event
* @adapter: adapter where link up occurred
*/
void
zfcp_cb_link_up(struct zfcp_adapter *adapter)
{
zfcp_cb_link_up_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.link_up;
if (cb)
cb(adapter);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
/**
* zfcp_cb_adapter_add - make callback for adapter add event
* @adapter: adapter which was added/activated
*/
void
zfcp_cb_adapter_add(struct zfcp_adapter *adapter)
{
zfcp_cb_adapter_add_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.adapter_add;
if (cb)
cb(adapter);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
/**
* zfcp_cb_port_add - make callback for port add event
* @port: port which was added
*/
void
zfcp_cb_port_add(struct zfcp_port *port)
{
zfcp_cb_port_add_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.port_add;
if (cb)
cb(port);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
/**
* zfcp_cb_unit_add - make callback for unit add event
* @unit: unit which was added
*/
void
zfcp_cb_unit_add(struct zfcp_unit *unit)
{
zfcp_cb_unit_add_t cb;
atomic_inc(&zfcp_callbacks.refcount);
cb = zfcp_callbacks.unit_add;
if (cb)
cb(unit);
if (atomic_dec_return(&zfcp_callbacks.refcount) == 0)
wake_up(&zfcp_callbacks.wq);
}
#undef ZFCP_LOG_AREA
EXPORT_SYMBOL(zfcp_sg_list_alloc);
EXPORT_SYMBOL(zfcp_sg_list_free);
EXPORT_SYMBOL(zfcp_sg_size);
EXPORT_SYMBOL(zfcp_sg_list_copy_from_user);
EXPORT_SYMBOL(zfcp_sg_list_copy_to_user);
EXPORT_SYMBOL(zfcp_get_unit_by_lun);
EXPORT_SYMBOL(zfcp_get_port_by_wwpn);
EXPORT_SYMBOL(zfcp_get_port_by_did);
EXPORT_SYMBOL(zfcp_get_adapter_by_busid);
EXPORT_SYMBOL(zfcp_register_callbacks);
EXPORT_SYMBOL(zfcp_unregister_callbacks);
EXPORT_SYMBOL(zfcp_port_enqueue);
EXPORT_SYMBOL(zfcp_unit_enqueue);
EXPORT_SYMBOL(zfcp_unit_dequeue);
EXPORT_SYMBOL(zfcp_check_ct_response);
......@@ -490,8 +490,8 @@ do { \
* Note, the leftmost status byte is common among adapter, port
* and unit
*/
#define ZFCP_COMMON_FLAGS 0xff000000
#define ZFCP_SPECIFIC_FLAGS 0x00ffffff
#define ZFCP_COMMON_FLAGS 0xfff00000
#define ZFCP_SPECIFIC_FLAGS 0x000fffff
/* common status bits */
#define ZFCP_STATUS_COMMON_REMOVE 0x80000000
......@@ -502,6 +502,7 @@ do { \
#define ZFCP_STATUS_COMMON_OPEN 0x04000000
#define ZFCP_STATUS_COMMON_CLOSING 0x02000000
#define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000
/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
......@@ -541,11 +542,9 @@ do { \
/* logical unit status */
#define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET 0x00000001
#define ZFCP_STATUS_UNIT_ACCESS_DENIED 0x00000002
#define ZFCP_STATUS_UNIT_ACCESS_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_ACCESS_READONLY 0x00000008
#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000010
#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
......@@ -1119,4 +1118,29 @@ zfcp_adapter_wait(struct zfcp_adapter *adapter)
wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
}
/*
* stuff needed for callback handling
*/
typedef void (*zfcp_cb_incoming_els_t) (struct zfcp_adapter *, void *);
typedef void (*zfcp_cb_link_down_t) (struct zfcp_adapter *);
typedef void (*zfcp_cb_link_up_t) (struct zfcp_adapter *);
typedef void (*zfcp_cb_adapter_add_t) (struct zfcp_adapter *);
typedef void (*zfcp_cb_port_add_t) (struct zfcp_port *);
typedef void (*zfcp_cb_unit_add_t) (struct zfcp_unit *);
struct zfcp_callbacks {
atomic_t refcount;
wait_queue_head_t wq;
zfcp_cb_incoming_els_t incoming_els;
zfcp_cb_link_down_t link_down;
zfcp_cb_link_up_t link_up;
zfcp_cb_adapter_add_t adapter_add;
zfcp_cb_port_add_t port_add;
zfcp_cb_unit_add_t unit_add;
};
extern struct zfcp_callbacks zfcp_callbacks;
#endif /* ZFCP_DEF_H */
......@@ -32,7 +32,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_ERP_REVISION "$Revision: 1.76 $"
#define ZFCP_ERP_REVISION "$Revision: 1.79 $"
#include "zfcp_ext.h"
......@@ -1785,34 +1785,22 @@ zfcp_erp_strategy_followup_actions(int action,
static int
zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
{
int retval = 0;
unsigned long flags;
struct zfcp_port *nport = adapter->nameserver_port;
read_lock_irqsave(&zfcp_data.config_lock, flags);
read_lock(&adapter->erp_lock);
if (list_empty(&adapter->erp_ready_head) &&
list_empty(&adapter->erp_running_head)) {
if (nport
&& atomic_test_mask(ZFCP_STATUS_COMMON_OPEN,
&nport->status)) {
debug_text_event(adapter->erp_dbf, 4, "a_cq_nspsd");
/* taking down nameserver port */
zfcp_erp_port_reopen_internal(nport,
ZFCP_STATUS_COMMON_RUNNING |
ZFCP_STATUS_COMMON_ERP_FAILED);
} else {
debug_text_event(adapter->erp_dbf, 4, "a_cq_wake");
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
&adapter->status);
wake_up(&adapter->erp_done_wqh);
}
} else
debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty");
read_unlock(&adapter->erp_lock);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
return retval;
return 0;
}
/**
......@@ -2808,10 +2796,11 @@ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
ZFCP_STATUS_COMMON_CLOSING |
ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_PORT_DID_DID |
ZFCP_STATUS_PORT_PHYS_CLOSING |
ZFCP_STATUS_PORT_INVALID_WWPN |
ZFCP_STATUS_PORT_ACCESS_DENIED, &port->status);
ZFCP_STATUS_PORT_INVALID_WWPN,
&port->status);
return retval;
}
......@@ -3016,9 +3005,10 @@ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
ZFCP_STATUS_COMMON_CLOSING |
ZFCP_STATUS_UNIT_ACCESS_DENIED |
ZFCP_STATUS_UNIT_ACCESS_SHARED |
ZFCP_STATUS_UNIT_ACCESS_READONLY, &unit->status);
ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_UNIT_SHARED |
ZFCP_STATUS_UNIT_READONLY,
&unit->status);
return retval;
}
......@@ -3357,9 +3347,11 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
if ((result == ZFCP_ERP_SUCCEEDED)
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status))
&& (!unit->device))
&& (!unit->device)) {
scsi_add_device(unit->port->adapter->scsi_host, 0,
unit->port->scsi_id, unit->scsi_lun);
zfcp_cb_unit_add(unit);
}
zfcp_unit_put(unit);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
......@@ -3478,4 +3470,126 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
}
/*
* function: zfcp_erp_port_access_denied
*
* purpose:
*/
void
zfcp_erp_port_access_denied(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
unsigned long flags;
debug_text_event(adapter->erp_dbf, 3, "p_access_block");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_erp_modify_port_status(port,
ZFCP_STATUS_COMMON_ERP_FAILED | ZFCP_STATUS_COMMON_ACCESS_DENIED,
ZFCP_SET);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
/*
* function: zfcp_erp_unit_access_denied
*
* purpose:
*/
void
zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
debug_text_event(adapter->erp_dbf, 3, "u_access_block");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
zfcp_erp_modify_unit_status(unit,
ZFCP_STATUS_COMMON_ERP_FAILED | ZFCP_STATUS_COMMON_ACCESS_DENIED,
ZFCP_SET);
}
/*
* function: zfcp_erp_adapter_access_changed
*
* purpose:
*/
void
zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
{
struct zfcp_port *port;
unsigned long flags;
debug_text_event(adapter->erp_dbf, 3, "a_access_unblock");
debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
zfcp_erp_port_access_changed(adapter->nameserver_port);
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &adapter->port_list_head, list)
if (port != adapter->nameserver_port)
zfcp_erp_port_access_changed(port);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
/*
* function: zfcp_erp_port_access_changed
*
* purpose:
*/
void
zfcp_erp_port_access_changed(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
struct zfcp_unit *unit;
debug_text_event(adapter->erp_dbf, 3, "p_access_unblock");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status)) {
if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
list_for_each_entry(unit, &port->unit_list_head, list)
zfcp_erp_unit_access_changed(unit);
return;
}
ZFCP_LOG_NORMAL("Trying to reopen port 0x%016Lx on adapter %s "
"due to update to access control table\n",
port->wwpn, zfcp_get_busid_by_adapter(adapter));
if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
ZFCP_LOG_NORMAL("Reopen of port 0x%016Lx on adapter %s failed\n",
port->wwpn, zfcp_get_busid_by_adapter(adapter));
}
/*
* function: zfcp_erp_unit_access_changed
*
* purpose:
*/
void
zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
debug_text_event(adapter->erp_dbf, 3, "u_access_unblock");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status))
return;
ZFCP_LOG_NORMAL("Trying to reopen unit 0x%016Lx "
"on port 0x%016Lx on adapter %s "
"due to update to access control table\n",
unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_adapter(adapter));
if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
ZFCP_LOG_NORMAL("Reopen of unit 0x%016Lx "
"on port 0x%016Lx on adapter %s failed\n",
unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_adapter(adapter));
}
#undef ZFCP_LOG_AREA
EXPORT_SYMBOL(zfcp_erp_wait);
EXPORT_SYMBOL(zfcp_erp_port_reopen);
EXPORT_SYMBOL(zfcp_erp_unit_reopen);
EXPORT_SYMBOL(zfcp_erp_unit_shutdown);
EXPORT_SYMBOL(zfcp_fsf_request_timeout_handler);
......@@ -32,7 +32,7 @@
#ifndef ZFCP_EXT_H
#define ZFCP_EXT_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_EXT_REVISION "$Revision: 1.58 $"
#define ZFCP_EXT_REVISION "$Revision: 1.60 $"
#include "zfcp_def.h"
......@@ -171,10 +171,34 @@ extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
extern int zfcp_test_link(struct zfcp_port *);
extern void zfcp_erp_port_access_denied(struct zfcp_port *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
extern void zfcp_erp_port_access_changed(struct zfcp_port *);
extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
/******************************** AUX ****************************************/
extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *,
void *, int);
extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *);
extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *,
struct fsf_status_read_buffer *, int);
extern int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
extern void zfcp_sg_list_free(struct zfcp_sg_list *);
extern int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void __user *,
size_t);
extern int zfcp_sg_list_copy_to_user(void __user *, struct zfcp_sg_list *,
size_t);
extern size_t zfcp_sg_size(struct scatterlist *, unsigned int);
void zfcp_register_callbacks(struct zfcp_callbacks *);
void zfcp_unregister_callbacks(void);
extern void zfcp_cb_incoming_els(struct zfcp_adapter *, void *);
extern void zfcp_cb_link_down(struct zfcp_adapter *);
extern void zfcp_cb_link_up(struct zfcp_adapter *);
extern void zfcp_cb_adapter_add(struct zfcp_adapter *);
extern void zfcp_cb_port_add(struct zfcp_port *);
extern void zfcp_cb_unit_add(struct zfcp_unit *);
#endif /* ZFCP_EXT_H */
......@@ -31,7 +31,7 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_FSF_C_REVISION "$Revision: 1.80 $"
#define ZFCP_FSF_C_REVISION "$Revision: 1.83 $"
#include "zfcp_ext.h"
......@@ -1020,6 +1020,8 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&adapter->status);
zfcp_erp_adapter_failed(adapter);
zfcp_cb_link_down(adapter);
break;
case FSF_STATUS_READ_LINK_UP:
......@@ -1036,6 +1038,8 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
| ZFCP_STATUS_COMMON_ERP_FAILED);
zfcp_cb_link_up(adapter);
break;
case FSF_STATUS_READ_CFDC_UPDATED:
......@@ -1043,6 +1047,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
zfcp_erp_adapter_access_changed(adapter);
break;
case FSF_STATUS_READ_CFDC_HARDENED:
......@@ -1620,7 +1625,8 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -2000,6 +2006,11 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
read_lock(&zfcp_data.config_lock);
port = zfcp_get_port_by_did(adapter, d_id);
if (port != NULL)
zfcp_erp_port_access_denied(port);
read_unlock(&zfcp_data.config_lock);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -2244,6 +2255,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
}
atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
&adapter->status);
zfcp_cb_adapter_add(adapter);
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
debug_text_event(adapter->erp_dbf, 0, "xchg-inco");
......@@ -2493,8 +2506,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
atomic_set_mask(ZFCP_STATUS_PORT_ACCESS_DENIED, &port->status);
zfcp_erp_port_failed(port);
zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -2886,9 +2898,8 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
case FSF_ACCESS_DENIED:
ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot close "
"physical port 0x%016Lx on "
"adapter %s\n", port->wwpn,
zfcp_get_busid_by_port(port));
"physical port 0x%016Lx on adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
for (counter = 0; counter < 2; counter++) {
subtable = header->fsf_status_qual.halfword[counter * 2];
rule = header->fsf_status_qual.halfword[counter * 2 + 1];
......@@ -2903,6 +2914,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -3073,7 +3085,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
u16 subtable, rule, counter;
u32 allowed, exclusive, readwrite;
unit = fsf_req->data.open_unit.unit;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
......@@ -3085,15 +3096,62 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
queue_designator = &header->fsf_status_qual.fsf_queue_designator;
allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED;
exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE_ACCESS;
exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE;
readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER;
atomic_clear_mask(ZFCP_STATUS_UNIT_ACCESS_DENIED |
ZFCP_STATUS_UNIT_ACCESS_SHARED |
ZFCP_STATUS_UNIT_ACCESS_READONLY,
if (!adapter->supported_features & FSF_FEATURE_CFDC)
goto no_cfdc;
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_UNIT_SHARED |
ZFCP_STATUS_UNIT_READONLY,
&unit->status);
if (!allowed)
atomic_set_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status);
if (!adapter->supported_features & FSF_FEATURE_LUN_SHARING)
goto no_lun_sharing;
if (!exclusive)
atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
if (!readwrite) {
atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
ZFCP_LOG_NORMAL("Unit 0x%016Lx on port 0x%016Lx on adapter %s "
"accessed read-only\n", unit->fcp_lun,
unit->port->wwpn, zfcp_get_busid_by_unit(unit));
}
if (exclusive && !readwrite) {
ZFCP_LOG_NORMAL("Exclusive access of read-only unit not "
"supported\n");
zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
goto skip_fsfstatus;
}
if (!exclusive && readwrite) {
ZFCP_LOG_NORMAL("Shared access of read-write unit is not "
"supported\n");
zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
goto skip_fsfstatus;
}
no_lun_sharing:
no_cfdc:
if (!(adapter->supported_features & FSF_FEATURE_CFDC) &&
(adapter->supported_features & FSF_FEATURE_LUN_SHARING)) {
ZFCP_LOG_NORMAL("LUN sharing without access control is not "
"supported.\n");
zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
goto skip_fsfstatus;
}
/* evaluate FSF status in QTCB */
switch (header->fsf_status) {
......@@ -3144,12 +3202,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
atomic_set_mask(ZFCP_STATUS_UNIT_ACCESS_DENIED, &unit->status);
atomic_clear_mask(ZFCP_STATUS_UNIT_ACCESS_SHARED,
&unit->status);
atomic_clear_mask(ZFCP_STATUS_UNIT_ACCESS_READONLY,
&unit->status);
zfcp_erp_unit_failed(unit);
zfcp_erp_unit_access_denied(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -3279,12 +3332,11 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
if (!exclusive)
atomic_set_mask(ZFCP_STATUS_UNIT_ACCESS_SHARED,
atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
&unit->status);
if (!readwrite) {
atomic_set_mask(
ZFCP_STATUS_UNIT_ACCESS_READONLY,
atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
&unit->status);
ZFCP_LOG_NORMAL("read-only access for unit "
"(adapter %s, wwpn=0x%016Lx, "
......@@ -3643,8 +3695,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
/* set FCP_LUN in FCP_CMND IU in QTCB */
fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
mask = ZFCP_STATUS_UNIT_ACCESS_READONLY |
ZFCP_STATUS_UNIT_ACCESS_SHARED;
mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED;
/* set task attributes in FCP_CMND IU in QTCB */
if (likely((scsi_cmnd->device->simple_tags) ||
......@@ -3986,6 +4037,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_unit_access_denied(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
......@@ -5086,3 +5138,7 @@ zfcp_fsf_req_cleanup(struct zfcp_fsf_req *fsf_req)
}
#undef ZFCP_LOG_AREA
EXPORT_SYMBOL(zfcp_fsf_exchange_port_data);
EXPORT_SYMBOL(zfcp_fsf_send_ct);
EXPORT_SYMBOL(zfcp_fsf_send_els);
......@@ -234,7 +234,7 @@
/* open LUN access flags*/
#define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000
#define FSF_UNIT_ACCESS_EXCLUSIVE_ACCESS 0x02000000
#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000
#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000
struct fsf_queue_designator;
......
......@@ -32,7 +32,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_SCSI_REVISION "$Revision: 1.71 $"
#define ZFCP_SCSI_REVISION "$Revision: 1.72 $"
#include "zfcp_ext.h"
......@@ -948,3 +948,6 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
};
#undef ZFCP_LOG_AREA
EXPORT_SYMBOL(zfcp_data);
EXPORT_SYMBOL(zfcp_scsi_command_sync);
......@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.46 $"
#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $"
#include "zfcp_ext.h"
......@@ -71,7 +71,7 @@ ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
(ZFCP_STATUS_PORT_ACCESS_DENIED, &port->status));
(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status));
/**
* zfcp_sysfs_unit_add_store - add a unit to sysfs tree
......
......@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.29 $"
#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $"
#include "zfcp_ext.h"
......@@ -69,11 +69,11 @@ ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
(ZFCP_STATUS_UNIT_ACCESS_DENIED, &unit->status));
(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status));
ZFCP_DEFINE_UNIT_ATTR(access_shared, "%d\n", atomic_test_mask
(ZFCP_STATUS_UNIT_ACCESS_SHARED, &unit->status));
(ZFCP_STATUS_UNIT_SHARED, &unit->status));
ZFCP_DEFINE_UNIT_ATTR(access_readonly, "%d\n", atomic_test_mask
(ZFCP_STATUS_UNIT_ACCESS_READONLY, &unit->status));
(ZFCP_STATUS_UNIT_READONLY, &unit->status));
/**
* zfcp_sysfs_unit_failed_store - failed state of unit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment