aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2010-09-08 08:39:54 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-09-16 22:54:16 -0400
commitfdbd1c5e27dabfa950d4b0f52a20069aeaf67b9d (patch)
tree402ea45cf57a2fdcef7a6011a1c64bc7d43cc66e /drivers/s390/scsi
parente4b9857fe628b453983cac89473a11a76a1f5786 (diff)
[SCSI] zfcp: Allow running unit/LUN shutdown without acquiring reference
With the change for the LUN data to be part of the scsi_device, the slave_destroy callback will be the final call to the zfcp_erp_unit_shutdown function. The erp tries to acquire a reference to run the action asynchronously and fail, if it cannot get the reference. But calling scsi_device_get from slave_destroy will fail, because the scsi_device is already in the state SDEV_DEL. Introduce a new call into the zfcp erp to solve this: The function zfcp_erp_unit_shutdown_wait will close the LUN and wait for the erp to finish without acquiring an additional reference. The wait allows to omit the reference; the caller waiting for the erp to finish already has a reference that holds the struct in place. 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>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_erp.c98
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
2 files changed, 63 insertions, 36 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 160b432c907f..50514b4c8732 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -21,6 +21,7 @@ enum zfcp_erp_act_flags {
21 ZFCP_STATUS_ERP_DISMISSING = 0x00100000, 21 ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
22 ZFCP_STATUS_ERP_DISMISSED = 0x00200000, 22 ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
23 ZFCP_STATUS_ERP_LOWMEM = 0x00400000, 23 ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
24 ZFCP_STATUS_ERP_NO_REF = 0x00800000,
24}; 25};
25 26
26enum zfcp_erp_steps { 27enum zfcp_erp_steps {
@@ -169,22 +170,22 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
169 return need; 170 return need;
170} 171}
171 172
172static struct zfcp_erp_action *zfcp_erp_setup_act(int need, 173static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
173 struct zfcp_adapter *adapter, 174 struct zfcp_adapter *adapter,
174 struct zfcp_port *port, 175 struct zfcp_port *port,
175 struct zfcp_unit *unit) 176 struct zfcp_unit *unit)
176{ 177{
177 struct zfcp_erp_action *erp_action; 178 struct zfcp_erp_action *erp_action;
178 u32 status = 0;
179 179
180 switch (need) { 180 switch (need) {
181 case ZFCP_ERP_ACTION_REOPEN_UNIT: 181 case ZFCP_ERP_ACTION_REOPEN_UNIT:
182 if (!get_device(&unit->dev)) 182 if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
183 return NULL; 183 if (!get_device(&unit->dev))
184 return NULL;
184 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); 185 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
185 erp_action = &unit->erp_action; 186 erp_action = &unit->erp_action;
186 if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) 187 if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
187 status = ZFCP_STATUS_ERP_CLOSE_ONLY; 188 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
188 break; 189 break;
189 190
190 case ZFCP_ERP_ACTION_REOPEN_PORT: 191 case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -195,7 +196,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
195 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); 196 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
196 erp_action = &port->erp_action; 197 erp_action = &port->erp_action;
197 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) 198 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
198 status = ZFCP_STATUS_ERP_CLOSE_ONLY; 199 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
199 break; 200 break;
200 201
201 case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 202 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
@@ -205,7 +206,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
205 erp_action = &adapter->erp_action; 206 erp_action = &adapter->erp_action;
206 if (!(atomic_read(&adapter->status) & 207 if (!(atomic_read(&adapter->status) &
207 ZFCP_STATUS_COMMON_RUNNING)) 208 ZFCP_STATUS_COMMON_RUNNING))
208 status = ZFCP_STATUS_ERP_CLOSE_ONLY; 209 act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
209 break; 210 break;
210 211
211 default: 212 default:
@@ -217,14 +218,15 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
217 erp_action->port = port; 218 erp_action->port = port;
218 erp_action->unit = unit; 219 erp_action->unit = unit;
219 erp_action->action = need; 220 erp_action->action = need;
220 erp_action->status = status; 221 erp_action->status = act_status;
221 222
222 return erp_action; 223 return erp_action;
223} 224}
224 225
225static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, 226static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
226 struct zfcp_port *port, 227 struct zfcp_port *port,
227 struct zfcp_unit *unit, char *id, void *ref) 228 struct zfcp_unit *unit, char *id, void *ref,
229 u32 act_status)
228{ 230{
229 int retval = 1, need; 231 int retval = 1, need;
230 struct zfcp_erp_action *act = NULL; 232 struct zfcp_erp_action *act = NULL;
@@ -236,10 +238,10 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
236 if (!need) 238 if (!need)
237 goto out; 239 goto out;
238 240
239 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); 241 act = zfcp_erp_setup_act(need, act_status, adapter, port, unit);
240 act = zfcp_erp_setup_act(need, adapter, port, unit);
241 if (!act) 242 if (!act)
242 goto out; 243 goto out;
244 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
243 ++adapter->erp_total_count; 245 ++adapter->erp_total_count;
244 list_add_tail(&act->list, &adapter->erp_ready_head); 246 list_add_tail(&act->list, &adapter->erp_ready_head);
245 wake_up(&adapter->erp_ready_wq); 247 wake_up(&adapter->erp_ready_wq);
@@ -262,7 +264,7 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
262 return -EIO; 264 return -EIO;
263 } 265 }
264 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, 266 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
265 adapter, NULL, NULL, id, ref); 267 adapter, NULL, NULL, id, ref, 0);
266} 268}
267 269
268/** 270/**
@@ -285,7 +287,7 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
285 zfcp_erp_adapter_failed(adapter, "erareo1", NULL); 287 zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
286 else 288 else
287 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, 289 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
288 NULL, NULL, id, ref); 290 NULL, NULL, id, ref, 0);
289 write_unlock_irqrestore(&adapter->erp_lock, flags); 291 write_unlock_irqrestore(&adapter->erp_lock, flags);
290} 292}
291 293
@@ -317,20 +319,6 @@ void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id,
317 zfcp_erp_port_reopen(port, clear | flags, id, ref); 319 zfcp_erp_port_reopen(port, clear | flags, id, ref);
318} 320}
319 321
320/**
321 * zfcp_erp_unit_shutdown - Shutdown unit
322 * @unit: Unit to shut down.
323 * @clear: Status flags to clear.
324 * @id: Id for debug trace event.
325 * @ref: Reference for debug trace event.
326 */
327void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
328 void *ref)
329{
330 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
331 zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
332}
333
334static void zfcp_erp_port_block(struct zfcp_port *port, int clear) 322static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
335{ 323{
336 zfcp_erp_modify_port_status(port, "erpblk1", NULL, 324 zfcp_erp_modify_port_status(port, "erpblk1", NULL,
@@ -348,7 +336,7 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
348 return; 336 return;
349 337
350 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, 338 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
351 port->adapter, port, NULL, id, ref); 339 port->adapter, port, NULL, id, ref, 0);
352} 340}
353 341
354/** 342/**
@@ -381,7 +369,7 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
381 } 369 }
382 370
383 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, 371 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
384 port->adapter, port, NULL, id, ref); 372 port->adapter, port, NULL, id, ref, 0);
385} 373}
386 374
387/** 375/**
@@ -412,7 +400,7 @@ static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
412} 400}
413 401
414static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, 402static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
415 void *ref) 403 void *ref, u32 act_status)
416{ 404{
417 struct zfcp_adapter *adapter = unit->port->adapter; 405 struct zfcp_adapter *adapter = unit->port->adapter;
418 406
@@ -422,7 +410,7 @@ static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
422 return; 410 return;
423 411
424 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, 412 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
425 adapter, unit->port, unit, id, ref); 413 adapter, unit->port, unit, id, ref, act_status);
426} 414}
427 415
428/** 416/**
@@ -439,8 +427,45 @@ void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
439 struct zfcp_adapter *adapter = port->adapter; 427 struct zfcp_adapter *adapter = port->adapter;
440 428
441 write_lock_irqsave(&adapter->erp_lock, flags); 429 write_lock_irqsave(&adapter->erp_lock, flags);
442 _zfcp_erp_unit_reopen(unit, clear, id, ref); 430 _zfcp_erp_unit_reopen(unit, clear, id, ref, 0);
431 write_unlock_irqrestore(&adapter->erp_lock, flags);
432}
433
434/**
435 * zfcp_erp_unit_shutdown - Shutdown unit
436 * @unit: Unit to shut down.
437 * @clear: Status flags to clear.
438 * @id: Id for debug trace event.
439 * @ref: Reference for debug trace event.
440 */
441void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
442 void *ref)
443{
444 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
445 zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
446}
447
448/**
449 * zfcp_erp_unit_shutdown_wait - Shutdown unit and wait for erp completion
450 * @unit: Unit to shut down.
451 * @id: Id for debug trace event.
452 *
453 * Do not acquire a reference for the unit when creating the ERP
454 * action. It is safe, because this function waits for the ERP to
455 * complete first.
456 */
457void zfcp_erp_unit_shutdown_wait(struct zfcp_unit *unit, char *id)
458{
459 unsigned long flags;
460 struct zfcp_port *port = unit->port;
461 struct zfcp_adapter *adapter = port->adapter;
462 int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
463
464 write_lock_irqsave(&adapter->erp_lock, flags);
465 _zfcp_erp_unit_reopen(unit, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF);
443 write_unlock_irqrestore(&adapter->erp_lock, flags); 466 write_unlock_irqrestore(&adapter->erp_lock, flags);
467
468 zfcp_erp_wait(adapter);
444} 469}
445 470
446static int status_change_set(unsigned long mask, atomic_t *status) 471static int status_change_set(unsigned long mask, atomic_t *status)
@@ -566,7 +591,7 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
566 591
567 read_lock(&port->unit_list_lock); 592 read_lock(&port->unit_list_lock);
568 list_for_each_entry(unit, &port->unit_list, list) 593 list_for_each_entry(unit, &port->unit_list, list)
569 _zfcp_erp_unit_reopen(unit, clear, id, ref); 594 _zfcp_erp_unit_reopen(unit, clear, id, ref, 0);
570 read_unlock(&port->unit_list_lock); 595 read_unlock(&port->unit_list_lock);
571} 596}
572 597
@@ -583,7 +608,7 @@ static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
583 _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); 608 _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
584 break; 609 break;
585 case ZFCP_ERP_ACTION_REOPEN_UNIT: 610 case ZFCP_ERP_ACTION_REOPEN_UNIT:
586 _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); 611 _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL, 0);
587 break; 612 break;
588 } 613 }
589} 614}
@@ -1143,7 +1168,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
1143 if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { 1168 if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
1144 _zfcp_erp_unit_reopen(unit, 1169 _zfcp_erp_unit_reopen(unit,
1145 ZFCP_STATUS_COMMON_ERP_FAILED, 1170 ZFCP_STATUS_COMMON_ERP_FAILED,
1146 "ersscg3", NULL); 1171 "ersscg3", NULL, 0);
1147 return ZFCP_ERP_EXIT; 1172 return ZFCP_ERP_EXIT;
1148 } 1173 }
1149 break; 1174 break;
@@ -1191,7 +1216,8 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1191 1216
1192 switch (act->action) { 1217 switch (act->action) {
1193 case ZFCP_ERP_ACTION_REOPEN_UNIT: 1218 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1194 put_device(&unit->dev); 1219 if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
1220 put_device(&unit->dev);
1195 break; 1221 break;
1196 1222
1197 case ZFCP_ERP_ACTION_REOPEN_PORT: 1223 case ZFCP_ERP_ACTION_REOPEN_PORT:
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 5c3966eaca51..3c90604076e0 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -80,6 +80,7 @@ extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32,
80 int); 80 int);
81extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *); 81extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *);
82extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *); 82extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *);
83extern void zfcp_erp_unit_shutdown_wait(struct zfcp_unit *, char *);
83extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *); 84extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *);
84extern int zfcp_erp_thread_setup(struct zfcp_adapter *); 85extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
85extern void zfcp_erp_thread_kill(struct zfcp_adapter *); 86extern void zfcp_erp_thread_kill(struct zfcp_adapter *);