[SCSI] hpsa: cap CCISS_PASSTHRU at 20 concurrent commands.
Cap CCISS_BIG_PASSTHRU as well. If an attempt is made to exceed this, ioctl() will return -1 with errno == EAGAIN. This is to prevent a userland program from exhausting all of pci_alloc_consistent memory. I've only seen this problem when running a special test program designed to provoke it. 20 concurrent commands via the passthru ioctls (not counting SG_IO) should be more than enough. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
e06c8e5c34
commit
0390f0c0df
|
@ -3222,6 +3222,36 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
|
||||||
c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
|
c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
|
||||||
(void) check_for_unit_attention(h, c);
|
(void) check_for_unit_attention(h, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int increment_passthru_count(struct ctlr_info *h)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&h->passthru_count_lock, flags);
|
||||||
|
if (h->passthru_count >= HPSA_MAX_CONCURRENT_PASSTHRUS) {
|
||||||
|
spin_unlock_irqrestore(&h->passthru_count_lock, flags);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
h->passthru_count++;
|
||||||
|
spin_unlock_irqrestore(&h->passthru_count_lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decrement_passthru_count(struct ctlr_info *h)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&h->passthru_count_lock, flags);
|
||||||
|
if (h->passthru_count <= 0) {
|
||||||
|
spin_unlock_irqrestore(&h->passthru_count_lock, flags);
|
||||||
|
/* not expecting to get here. */
|
||||||
|
dev_warn(&h->pdev->dev, "Bug detected, passthru_count seems to be incorrect.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
h->passthru_count--;
|
||||||
|
spin_unlock_irqrestore(&h->passthru_count_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioctl
|
* ioctl
|
||||||
*/
|
*/
|
||||||
|
@ -3229,6 +3259,7 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
struct ctlr_info *h;
|
struct ctlr_info *h;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
h = sdev_to_hba(dev);
|
h = sdev_to_hba(dev);
|
||||||
|
|
||||||
|
@ -3243,9 +3274,17 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
|
||||||
case CCISS_GETDRIVVER:
|
case CCISS_GETDRIVVER:
|
||||||
return hpsa_getdrivver_ioctl(h, argp);
|
return hpsa_getdrivver_ioctl(h, argp);
|
||||||
case CCISS_PASSTHRU:
|
case CCISS_PASSTHRU:
|
||||||
return hpsa_passthru_ioctl(h, argp);
|
if (increment_passthru_count(h))
|
||||||
|
return -EAGAIN;
|
||||||
|
rc = hpsa_passthru_ioctl(h, argp);
|
||||||
|
decrement_passthru_count(h);
|
||||||
|
return rc;
|
||||||
case CCISS_BIG_PASSTHRU:
|
case CCISS_BIG_PASSTHRU:
|
||||||
return hpsa_big_passthru_ioctl(h, argp);
|
if (increment_passthru_count(h))
|
||||||
|
return -EAGAIN;
|
||||||
|
rc = hpsa_big_passthru_ioctl(h, argp);
|
||||||
|
decrement_passthru_count(h);
|
||||||
|
return rc;
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
@ -4835,6 +4874,7 @@ reinit_after_soft_reset:
|
||||||
INIT_LIST_HEAD(&h->reqQ);
|
INIT_LIST_HEAD(&h->reqQ);
|
||||||
spin_lock_init(&h->lock);
|
spin_lock_init(&h->lock);
|
||||||
spin_lock_init(&h->scan_lock);
|
spin_lock_init(&h->scan_lock);
|
||||||
|
spin_lock_init(&h->passthru_count_lock);
|
||||||
rc = hpsa_pci_init(h);
|
rc = hpsa_pci_init(h);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto clean1;
|
goto clean1;
|
||||||
|
|
|
@ -114,6 +114,11 @@ struct ctlr_info {
|
||||||
struct TransTable_struct *transtable;
|
struct TransTable_struct *transtable;
|
||||||
unsigned long transMethod;
|
unsigned long transMethod;
|
||||||
|
|
||||||
|
/* cap concurrent passthrus at some reasonable maximum */
|
||||||
|
#define HPSA_MAX_CONCURRENT_PASSTHRUS (20)
|
||||||
|
spinlock_t passthru_count_lock; /* protects passthru_count */
|
||||||
|
int passthru_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Performant mode completion buffers
|
* Performant mode completion buffers
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue