[SCSI] zfcp: Change spin_lock_bh to spin_lock_irq to fix lockdep warning

With the change to use the data on the SCSI device, iterating through
all LUNs/scsi_devices takes the SCSI host_lock. This triggers warnings
from the lock dependency checker:

=========================================================
[ INFO: possible irq lock inversion dependency detected ]
2.6.34.1 #97
---------------------------------------------------------
chchp/3224 just changed the state of lock:
 (&(shost->host_lock)->rlock){-.-...}, at: [<00000000003a73f4>] __scsi_iterate_devices+0x38/0xbc
but this lock took another, HARDIRQ-unsafe lock in the past:
 (&(&qdio->req_q_lock)->rlock){+.-...}

and interrupts could create inverse lock ordering between them.

other info that might help us debug this: [   24.972394] 2 locks held by chchp/3224:
 #0:  (&(sch->lock)->rlock){-.-...}, at: [<0000000000401efa>] do_IRQ+0xb2/0x1e4
 #1:  (&adapter->port_list_lock){.-....}, at: [<0000000000490302>] zfcp_erp_modify_adapter_status+0x9e/0x16c
[...]

=========================================================
[ INFO: possible irq lock inversion dependency detected ]
2.6.34.1 #98
---------------------------------------------------------
chchp/3235 just changed the state of lock:
 (&(shost->host_lock)->rlock){-.-...}, at: [<00000000003a73f4>] __scsi_iterate_devices+0x38/0xbc
but this lock took another, HARDIRQ-unsafe lock in the past:
 (&(&qdio->stat_lock)->rlock){+.-...}

and interrupts could create inverse lock ordering between them.

other info that might help us debug this:
2 locks held by chchp/3235:
 #0:  (&(sch->lock)->rlock){-.-...}, at: [<0000000000401efa>] do_IRQ+0xb2/0x1e4
 #1:  (&adapter->port_list_lock){.-.-..}, at: [<00000000004902f6>] zfcp_erp_modify_adapter_status+0x9e/0x16c
[...]

To stop this warning, change the request queue lock to disable irqs,
not only softirq. The changes are required only outside of the
critical "send fcp command" path.

Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Christof Schmitt 2010-09-08 14:39:57 +02:00 committed by James Bottomley
parent f8210e3488
commit 44a24cb373
2 changed files with 46 additions and 44 deletions

View File

@ -773,7 +773,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
struct fsf_status_read_buffer *sr_buf; struct fsf_status_read_buffer *sr_buf;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -807,7 +807,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL); zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -876,7 +876,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
unsigned long old_req_id = (unsigned long) scmnd->host_scribble; unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND, req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
@ -907,7 +907,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
req = NULL; req = NULL;
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return req; return req;
} }
@ -1046,7 +1046,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int ret = -EIO; int ret = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1078,7 +1078,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
failed_send: failed_send:
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return ret; return ret;
} }
@ -1142,7 +1142,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
struct zfcp_qdio *qdio = adapter->qdio; struct zfcp_qdio *qdio = adapter->qdio;
int ret = -EIO; int ret = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1178,7 +1178,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
failed_send: failed_send:
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return ret; return ret;
} }
@ -1188,7 +1188,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct zfcp_qdio *qdio = erp_action->adapter->qdio;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1220,7 +1220,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1230,7 +1230,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
struct zfcp_fsf_req *req = NULL; struct zfcp_fsf_req *req = NULL;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out_unlock; goto out_unlock;
@ -1256,7 +1256,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req); retval = zfcp_fsf_req_send(req);
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
if (!retval) if (!retval)
wait_for_completion(&req->completion); wait_for_completion(&req->completion);
@ -1264,7 +1264,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
return retval; return retval;
out_unlock: out_unlock:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1282,7 +1282,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP; return -EOPNOTSUPP;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1309,7 +1309,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1328,7 +1328,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP; return -EOPNOTSUPP;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out_unlock; goto out_unlock;
@ -1348,7 +1348,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
req->handler = zfcp_fsf_exchange_port_data_handler; req->handler = zfcp_fsf_exchange_port_data_handler;
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req); retval = zfcp_fsf_req_send(req);
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
if (!retval) if (!retval)
wait_for_completion(&req->completion); wait_for_completion(&req->completion);
@ -1358,7 +1358,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
return retval; return retval;
out_unlock: out_unlock:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1442,7 +1442,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1473,7 +1473,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
put_device(&port->dev); put_device(&port->dev);
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1510,7 +1510,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1539,7 +1539,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1585,7 +1585,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1610,7 +1610,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
if (retval) if (retval)
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1638,7 +1638,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1663,7 +1663,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
if (retval) if (retval)
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1728,7 +1728,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1757,7 +1757,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1900,7 +1900,7 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -1933,7 +1933,7 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -1987,7 +1987,7 @@ int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req; struct zfcp_fsf_req *req;
int retval = -EIO; int retval = -EIO;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -2017,7 +2017,7 @@ int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0; erp_action->fsf_req_id = 0;
} }
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return retval; return retval;
} }
@ -2363,7 +2363,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
ZFCP_STATUS_COMMON_UNBLOCKED))) ZFCP_STATUS_COMMON_UNBLOCKED)))
return NULL; return NULL;
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -2397,7 +2397,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
zfcp_fsf_req_free(req); zfcp_fsf_req_free(req);
req = NULL; req = NULL;
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return req; return req;
} }
@ -2433,7 +2433,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio)) if (zfcp_qdio_sbal_get(qdio))
goto out; goto out;
@ -2460,7 +2460,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req); retval = zfcp_fsf_req_send(req);
out: out:
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
if (!retval) { if (!retval) {
wait_for_completion(&req->completion); wait_for_completion(&req->completion);

View File

@ -60,13 +60,11 @@ static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
unsigned long long now, span; unsigned long long now, span;
int used; int used;
spin_lock(&qdio->stat_lock);
now = get_clock_monotonic(); now = get_clock_monotonic();
span = (now - qdio->req_q_time) >> 12; span = (now - qdio->req_q_time) >> 12;
used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free); used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
qdio->req_q_util += used * span; qdio->req_q_util += used * span;
qdio->req_q_time = now; qdio->req_q_time = now;
spin_unlock(&qdio->stat_lock);
} }
static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
@ -84,7 +82,9 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
/* cleanup all SBALs being program-owned now */ /* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(qdio->req_q, idx, count); zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
spin_lock_irq(&qdio->stat_lock);
zfcp_qdio_account(qdio); zfcp_qdio_account(qdio);
spin_unlock_irq(&qdio->stat_lock);
atomic_add(count, &qdio->req_q_free); atomic_add(count, &qdio->req_q_free);
wake_up(&qdio->req_q_wq); wake_up(&qdio->req_q_wq);
} }
@ -201,11 +201,11 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
{ {
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
if (atomic_read(&qdio->req_q_free) || if (atomic_read(&qdio->req_q_free) ||
!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return 1; return 1;
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
return 0; return 0;
} }
@ -223,7 +223,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
{ {
long ret; long ret;
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
ret = wait_event_interruptible_timeout(qdio->req_q_wq, ret = wait_event_interruptible_timeout(qdio->req_q_wq,
zfcp_qdio_sbal_check(qdio), 5 * HZ); zfcp_qdio_sbal_check(qdio), 5 * HZ);
@ -239,7 +239,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL); zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
} }
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
return -EIO; return -EIO;
} }
@ -254,7 +254,9 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
int retval; int retval;
u8 sbal_number = q_req->sbal_number; u8 sbal_number = q_req->sbal_number;
spin_lock(&qdio->stat_lock);
zfcp_qdio_account(qdio); zfcp_qdio_account(qdio);
spin_unlock(&qdio->stat_lock);
retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
q_req->sbal_first, sbal_number); q_req->sbal_first, sbal_number);
@ -328,9 +330,9 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
return; return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
spin_lock_bh(&qdio->req_q_lock); spin_lock_irq(&qdio->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
spin_unlock_bh(&qdio->req_q_lock); spin_unlock_irq(&qdio->req_q_lock);
wake_up(&qdio->req_q_wq); wake_up(&qdio->req_q_wq);