Skip to content

Commit 2db4215

Browse files
morbidrsamartinkpetersen
authored andcommitted
scsi: sd_zbc: Update write pointer offset cache
Recent changes changed the completion of SCSI commands from Soft-IRQ context to IRQ context. This triggers the following warning, when we're completing writes to zoned block devices that go through the zone append emulation: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.12.0-rc2+ Rust-for-Linux#2 Hardware name: Supermicro Super Server/X10SRL-F, BIOS 2.0 12/17/2015 RIP: 0010:__local_bh_disable_ip+0x3f/0x50 RSP: 0018:ffff8883e1409ba8 EFLAGS: 00010006 RAX: 0000000080010001 RBX: 0000000000000001 RCX: 0000000000000013 RDX: ffff888129e4d200 RSI: 0000000000000201 RDI: ffffffff915b9dbd RBP: ffff888113e9a540 R08: ffff888113e9a540 R09: 00000000000077f0 R10: 0000000000080000 R11: 0000000000000001 R12: ffff888129e4d200 R13: 0000000000001000 R14: 00000000000077f0 R15: ffff888129e4d218 FS: 0000000000000000(0000) GS:ffff8883e1400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f2f8418ebc0 CR3: 000000021202a006 CR4: 00000000001706f0 Call Trace: <IRQ> _raw_spin_lock_bh+0x18/0x40 sd_zbc_complete+0x43d/0x1150 sd_done+0x631/0x1040 ? mark_lock+0xe4/0x2fd0 ? provisioning_mode_store+0x3f0/0x3f0 scsi_finish_command+0x31b/0x5c0 _scsih_io_done+0x960/0x29e0 [mpt3sas] ? mpt3sas_scsih_scsi_lookup_get+0x1c7/0x340 [mpt3sas] ? __lock_acquire+0x166b/0x58b0 ? _get_st_from_smid+0x4a/0x80 [mpt3sas] _base_process_reply_queue+0x23f/0x26e0 [mpt3sas] ? lock_is_held_type+0x98/0x110 ? find_held_lock+0x2c/0x110 ? mpt3sas_base_sync_reply_irqs+0x360/0x360 [mpt3sas] _base_interrupt+0x8d/0xd0 [mpt3sas] ? rcu_read_lock_sched_held+0x3f/0x70 __handle_irq_event_percpu+0x24d/0x600 handle_irq_event+0xef/0x240 ? handle_irq_event_percpu+0x110/0x110 handle_edge_irq+0x1f6/0xb60 __common_interrupt+0x75/0x160 common_interrupt+0x7b/0xa0 </IRQ> asm_common_interrupt+0x1e/0x40 Don't use spin_lock_bh() to protect the update of the write pointer offset cache, but use spin_lock_irqsave() for it. Link: https://lore.kernel.org/r/3cfebe48d09db73041b7849be71ffbcec7ee40b3.1615369586.git.johannes.thumshirn@wdc.com Fixes: 664f0dc ("scsi: mpt3sas: Add support for shared host tagset for CPU hotplug") Reported-by: Shinichiro Kawasaki <[email protected]> Tested-by: Shin'ichiro Kawasaki <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Signed-off-by: Johannes Thumshirn <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 19f1bc7 commit 2db4215

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

drivers/scsi/sd_zbc.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -280,27 +280,28 @@ static int sd_zbc_update_wp_offset_cb(struct blk_zone *zone, unsigned int idx,
280280
static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
281281
{
282282
struct scsi_disk *sdkp;
283+
unsigned long flags;
283284
unsigned int zno;
284285
int ret;
285286

286287
sdkp = container_of(work, struct scsi_disk, zone_wp_offset_work);
287288

288-
spin_lock_bh(&sdkp->zones_wp_offset_lock);
289+
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
289290
for (zno = 0; zno < sdkp->nr_zones; zno++) {
290291
if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
291292
continue;
292293

293-
spin_unlock_bh(&sdkp->zones_wp_offset_lock);
294+
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
294295
ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf,
295296
SD_BUF_SIZE,
296297
zno * sdkp->zone_blocks, true);
297-
spin_lock_bh(&sdkp->zones_wp_offset_lock);
298+
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
298299
if (!ret)
299300
sd_zbc_parse_report(sdkp, sdkp->zone_wp_update_buf + 64,
300301
zno, sd_zbc_update_wp_offset_cb,
301302
sdkp);
302303
}
303-
spin_unlock_bh(&sdkp->zones_wp_offset_lock);
304+
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
304305

305306
scsi_device_put(sdkp->device);
306307
}
@@ -324,6 +325,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
324325
struct request *rq = cmd->request;
325326
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
326327
unsigned int wp_offset, zno = blk_rq_zone_no(rq);
328+
unsigned long flags;
327329
blk_status_t ret;
328330

329331
ret = sd_zbc_cmnd_checks(cmd);
@@ -337,7 +339,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
337339
if (!blk_req_zone_write_trylock(rq))
338340
return BLK_STS_ZONE_RESOURCE;
339341

340-
spin_lock_bh(&sdkp->zones_wp_offset_lock);
342+
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
341343
wp_offset = sdkp->zones_wp_offset[zno];
342344
switch (wp_offset) {
343345
case SD_ZBC_INVALID_WP_OFST:
@@ -366,7 +368,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
366368

367369
*lba += wp_offset;
368370
}
369-
spin_unlock_bh(&sdkp->zones_wp_offset_lock);
371+
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
370372
if (ret)
371373
blk_req_zone_write_unlock(rq);
372374
return ret;
@@ -445,14 +447,15 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
445447
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
446448
unsigned int zno = blk_rq_zone_no(rq);
447449
enum req_opf op = req_op(rq);
450+
unsigned long flags;
448451

449452
/*
450453
* If we got an error for a command that needs updating the write
451454
* pointer offset cache, we must mark the zone wp offset entry as
452455
* invalid to force an update from disk the next time a zone append
453456
* command is issued.
454457
*/
455-
spin_lock_bh(&sdkp->zones_wp_offset_lock);
458+
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
456459

457460
if (result && op != REQ_OP_ZONE_RESET_ALL) {
458461
if (op == REQ_OP_ZONE_APPEND) {
@@ -496,7 +499,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
496499
}
497500

498501
unlock_wp_offset:
499-
spin_unlock_bh(&sdkp->zones_wp_offset_lock);
502+
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
500503

501504
return good_bytes;
502505
}

0 commit comments

Comments
 (0)