Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: convert host_busy to atomic_t

Avoid taking the host-wide host_lock to check the per-host queue limit.
Instead we do an atomic_inc_return early on to grab our slot in the queue,
and if necessary decrement it after finishing all checks.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Webb Scales <webbnh@hp.com>
Acked-by: Jens Axboe <axboe@kernel.dk>
Tested-by: Bart Van Assche <bvanassche@acm.org>
Tested-by: Robert Elliott <elliott@hp.com>

+69 -48
+2 -2
drivers/scsi/advansys.c
··· 2512 2512 2513 2513 printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); 2514 2514 printk(" host_busy %u, host_no %d,\n", 2515 - s->host_busy, s->host_no); 2515 + atomic_read(&s->host_busy), s->host_no); 2516 2516 2517 2517 printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", 2518 2518 (ulong)s->base, (ulong)s->io_port, boardp->irq); ··· 3346 3346 3347 3347 seq_printf(m, 3348 3348 " host_busy %u, max_id %u, max_lun %llu, max_channel %u\n", 3349 - shost->host_busy, shost->max_id, 3349 + atomic_read(&shost->host_busy), shost->max_id, 3350 3350 shost->max_lun, shost->max_channel); 3351 3351 3352 3352 seq_printf(m,
+2 -2
drivers/scsi/libiscsi.c
··· 2971 2971 */ 2972 2972 for (;;) { 2973 2973 spin_lock_irqsave(session->host->host_lock, flags); 2974 - if (!session->host->host_busy) { /* OK for ERL == 0 */ 2974 + if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */ 2975 2975 spin_unlock_irqrestore(session->host->host_lock, flags); 2976 2976 break; 2977 2977 } ··· 2979 2979 msleep_interruptible(500); 2980 2980 iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): " 2981 2981 "host_busy %d host_failed %d\n", 2982 - session->host->host_busy, 2982 + atomic_read(&session->host->host_busy), 2983 2983 session->host->host_failed); 2984 2984 /* 2985 2985 * force eh_abort() to unblock
+3 -2
drivers/scsi/libsas/sas_scsi_host.c
··· 813 813 spin_unlock_irq(shost->host_lock); 814 814 815 815 SAS_DPRINTK("Enter %s busy: %d failed: %d\n", 816 - __func__, shost->host_busy, shost->host_failed); 816 + __func__, atomic_read(&shost->host_busy), shost->host_failed); 817 817 /* 818 818 * Deal with commands that still have SAS tasks (i.e. they didn't 819 819 * complete via the normal sas_task completion mechanism), ··· 858 858 goto retry; 859 859 860 860 SAS_DPRINTK("--- Exit %s: busy: %d failed: %d tries: %d\n", 861 - __func__, shost->host_busy, shost->host_failed, tries); 861 + __func__, atomic_read(&shost->host_busy), 862 + shost->host_failed, tries); 862 863 } 863 864 864 865 enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
+1 -1
drivers/scsi/qlogicpti.c
··· 959 959 /* Temporary workaround until bug is found and fixed (one bug has been found 960 960 already, but fixing it makes things even worse) -jj */ 961 961 int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64; 962 - host->can_queue = host->host_busy + num_free; 962 + host->can_queue = atomic_read(&host->host_busy) + num_free; 963 963 host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); 964 964 } 965 965
+1 -1
drivers/scsi/scsi.c
··· 600 600 if (level > 3) 601 601 scmd_printk(KERN_INFO, cmd, 602 602 "scsi host busy %d failed %d\n", 603 - cmd->device->host->host_busy, 603 + atomic_read(&cmd->device->host->host_busy), 604 604 cmd->device->host->host_failed); 605 605 } 606 606 }
+4 -3
drivers/scsi/scsi_error.c
··· 59 59 /* called with shost->host_lock held */ 60 60 void scsi_eh_wakeup(struct Scsi_Host *shost) 61 61 { 62 - if (shost->host_busy == shost->host_failed) { 62 + if (atomic_read(&shost->host_busy) == shost->host_failed) { 63 63 trace_scsi_eh_wakeup(shost); 64 64 wake_up_process(shost->ehandler); 65 65 SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost, ··· 2164 2164 while (!kthread_should_stop()) { 2165 2165 set_current_state(TASK_INTERRUPTIBLE); 2166 2166 if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || 2167 - shost->host_failed != shost->host_busy) { 2167 + shost->host_failed != atomic_read(&shost->host_busy)) { 2168 2168 SCSI_LOG_ERROR_RECOVERY(1, 2169 2169 shost_printk(KERN_INFO, shost, 2170 2170 "scsi_eh_%d: sleeping\n", ··· 2178 2178 shost_printk(KERN_INFO, shost, 2179 2179 "scsi_eh_%d: waking up %d/%d/%d\n", 2180 2180 shost->host_no, shost->host_eh_scheduled, 2181 - shost->host_failed, shost->host_busy)); 2181 + shost->host_failed, 2182 + atomic_read(&shost->host_busy))); 2182 2183 2183 2184 /* 2184 2185 * We have a host that is failing for some reason. Figure out
+45 -29
drivers/scsi/scsi_lib.c
··· 292 292 struct scsi_target *starget = scsi_target(sdev); 293 293 unsigned long flags; 294 294 295 - spin_lock_irqsave(shost->host_lock, flags); 296 - shost->host_busy--; 295 + atomic_dec(&shost->host_busy); 297 296 atomic_dec(&starget->target_busy); 297 + 298 298 if (unlikely(scsi_host_in_recovery(shost) && 299 - (shost->host_failed || shost->host_eh_scheduled))) 299 + (shost->host_failed || shost->host_eh_scheduled))) { 300 + spin_lock_irqsave(shost->host_lock, flags); 300 301 scsi_eh_wakeup(shost); 301 - spin_unlock(shost->host_lock); 302 - spin_lock(sdev->request_queue->queue_lock); 302 + spin_unlock_irqrestore(shost->host_lock, flags); 303 + } 304 + 305 + spin_lock_irqsave(sdev->request_queue->queue_lock, flags); 303 306 sdev->device_busy--; 304 307 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 305 308 } ··· 370 367 371 368 static inline int scsi_host_is_busy(struct Scsi_Host *shost) 372 369 { 373 - if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) || 370 + if ((shost->can_queue > 0 && 371 + atomic_read(&shost->host_busy) >= shost->can_queue) || 374 372 shost->host_blocked || shost->host_self_blocked) 375 373 return 1; 376 374 ··· 1338 1334 struct Scsi_Host *shost, 1339 1335 struct scsi_device *sdev) 1340 1336 { 1341 - int ret = 0; 1342 - 1343 - spin_lock_irq(shost->host_lock); 1337 + unsigned int busy; 1344 1338 1345 1339 if (scsi_host_in_recovery(shost)) 1346 - goto out; 1347 - if (shost->host_busy == 0 && shost->host_blocked) { 1340 + return 0; 1341 + 1342 + busy = atomic_inc_return(&shost->host_busy) - 1; 1343 + if (shost->host_blocked) { 1344 + if (busy) 1345 + goto starved; 1346 + 1348 1347 /* 1349 1348 * unblock after host_blocked iterates to zero 1350 1349 */ 1351 - if (--shost->host_blocked != 0) 1352 - goto out; 1350 + spin_lock_irq(shost->host_lock); 1351 + if (--shost->host_blocked != 0) { 1352 + spin_unlock_irq(shost->host_lock); 1353 + goto out_dec; 1354 + } 1355 + spin_unlock_irq(shost->host_lock); 1353 1356 1354 1357 SCSI_LOG_MLQUEUE(3, 1355 1358 shost_printk(KERN_INFO, shost, 1356 1359 "unblocking host at zero depth\n")); 1357 1360 } 1358 - if (scsi_host_is_busy(shost)) { 1359 - if (list_empty(&sdev->starved_entry)) 1360 - list_add_tail(&sdev->starved_entry, &shost->starved_list); 1361 - goto out; 1362 - } 1361 + 1362 + if (shost->can_queue > 0 && busy >= shost->can_queue) 1363 + goto starved; 1364 + if (shost->host_self_blocked) 1365 + goto starved; 1363 1366 1364 1367 /* We're OK to process the command, so we can't be starved */ 1365 - if (!list_empty(&sdev->starved_entry)) 1366 - list_del_init(&sdev->starved_entry); 1368 + if (!list_empty(&sdev->starved_entry)) { 1369 + spin_lock_irq(shost->host_lock); 1370 + if (!list_empty(&sdev->starved_entry)) 1371 + list_del_init(&sdev->starved_entry); 1372 + spin_unlock_irq(shost->host_lock); 1373 + } 1367 1374 1368 - shost->host_busy++; 1369 - ret = 1; 1370 - out: 1375 + return 1; 1376 + 1377 + starved: 1378 + spin_lock_irq(shost->host_lock); 1379 + if (list_empty(&sdev->starved_entry)) 1380 + list_add_tail(&sdev->starved_entry, &shost->starved_list); 1371 1381 spin_unlock_irq(shost->host_lock); 1372 - return ret; 1382 + out_dec: 1383 + atomic_dec(&shost->host_busy); 1384 + return 0; 1373 1385 } 1374 1386 1375 1387 /* ··· 1449 1429 * with the locks as normal issue path does. 1450 1430 */ 1451 1431 sdev->device_busy++; 1452 - spin_unlock(sdev->request_queue->queue_lock); 1453 - spin_lock(shost->host_lock); 1454 - shost->host_busy++; 1432 + atomic_inc(&shost->host_busy); 1455 1433 atomic_inc(&starget->target_busy); 1456 - spin_unlock(shost->host_lock); 1457 - spin_lock(sdev->request_queue->queue_lock); 1458 1434 1459 1435 blk_complete_request(req); 1460 1436 }
+8 -1
drivers/scsi/scsi_sysfs.c
··· 334 334 static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); 335 335 336 336 shost_rd_attr(unique_id, "%u\n"); 337 - shost_rd_attr(host_busy, "%hu\n"); 338 337 shost_rd_attr(cmd_per_lun, "%hd\n"); 339 338 shost_rd_attr(can_queue, "%hd\n"); 340 339 shost_rd_attr(sg_tablesize, "%hu\n"); ··· 342 343 shost_rd_attr(prot_capabilities, "%u\n"); 343 344 shost_rd_attr(prot_guard_type, "%hd\n"); 344 345 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); 346 + 347 + static ssize_t 348 + show_host_busy(struct device *dev, struct device_attribute *attr, char *buf) 349 + { 350 + struct Scsi_Host *shost = class_to_shost(dev); 351 + return snprintf(buf, 20, "%d\n", atomic_read(&shost->host_busy)); 352 + } 353 + static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL); 345 354 346 355 static struct attribute *scsi_sysfs_shost_attrs[] = { 347 356 &dev_attr_unique_id.attr,
+3 -7
include/scsi/scsi_host.h
··· 582 582 */ 583 583 struct blk_queue_tag *bqt; 584 584 585 - /* 586 - * The following two fields are protected with host_lock; 587 - * however, eh routines can safely access during eh processing 588 - * without acquiring the lock. 589 - */ 590 - unsigned int host_busy; /* commands actually active on low-level */ 591 - unsigned int host_failed; /* commands that failed. */ 585 + atomic_t host_busy; /* commands actually active on low-level */ 586 + unsigned int host_failed; /* commands that failed. 587 + protected by host_lock */ 592 588 unsigned int host_eh_scheduled; /* EH scheduled without command */ 593 589 594 590 unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */