diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2013-09-23 14:34:12 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-19 10:38:56 -0500 |
commit | 0390f0c0dfb540149d7369276b17ec53caf506cb (patch) | |
tree | 2a621fff7b52ca27a9e1a66c168b940d599222f2 /drivers/scsi/hpsa.c | |
parent | e06c8e5c34498d1ea0468401012be8d1c853c585 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 6cc91f83aa69..9acfce3bbe78 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -3222,6 +3222,36 @@ static void check_ioctl_unit_attention(struct ctlr_info *h, | |||
3222 | c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) | 3222 | c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) |
3223 | (void) check_for_unit_attention(h, c); | 3223 | (void) check_for_unit_attention(h, c); |
3224 | } | 3224 | } |
3225 | |||
3226 | static int increment_passthru_count(struct ctlr_info *h) | ||
3227 | { | ||
3228 | unsigned long flags; | ||
3229 | |||
3230 | spin_lock_irqsave(&h->passthru_count_lock, flags); | ||
3231 | if (h->passthru_count >= HPSA_MAX_CONCURRENT_PASSTHRUS) { | ||
3232 | spin_unlock_irqrestore(&h->passthru_count_lock, flags); | ||
3233 | return -1; | ||
3234 | } | ||
3235 | h->passthru_count++; | ||
3236 | spin_unlock_irqrestore(&h->passthru_count_lock, flags); | ||
3237 | return 0; | ||
3238 | } | ||
3239 | |||
3240 | static void decrement_passthru_count(struct ctlr_info *h) | ||
3241 | { | ||
3242 | unsigned long flags; | ||
3243 | |||
3244 | spin_lock_irqsave(&h->passthru_count_lock, flags); | ||
3245 | if (h->passthru_count <= 0) { | ||
3246 | spin_unlock_irqrestore(&h->passthru_count_lock, flags); | ||
3247 | /* not expecting to get here. */ | ||
3248 | dev_warn(&h->pdev->dev, "Bug detected, passthru_count seems to be incorrect.\n"); | ||
3249 | return; | ||
3250 | } | ||
3251 | h->passthru_count--; | ||
3252 | spin_unlock_irqrestore(&h->passthru_count_lock, flags); | ||
3253 | } | ||
3254 | |||
3225 | /* | 3255 | /* |
3226 | * ioctl | 3256 | * ioctl |
3227 | */ | 3257 | */ |
@@ -3229,6 +3259,7 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg) | |||
3229 | { | 3259 | { |
3230 | struct ctlr_info *h; | 3260 | struct ctlr_info *h; |
3231 | void __user *argp = (void __user *)arg; | 3261 | void __user *argp = (void __user *)arg; |
3262 | int rc; | ||
3232 | 3263 | ||
3233 | h = sdev_to_hba(dev); | 3264 | h = sdev_to_hba(dev); |
3234 | 3265 | ||
@@ -3243,9 +3274,17 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg) | |||
3243 | case CCISS_GETDRIVVER: | 3274 | case CCISS_GETDRIVVER: |
3244 | return hpsa_getdrivver_ioctl(h, argp); | 3275 | return hpsa_getdrivver_ioctl(h, argp); |
3245 | case CCISS_PASSTHRU: | 3276 | case CCISS_PASSTHRU: |
3246 | return hpsa_passthru_ioctl(h, argp); | 3277 | if (increment_passthru_count(h)) |
3278 | return -EAGAIN; | ||
3279 | rc = hpsa_passthru_ioctl(h, argp); | ||
3280 | decrement_passthru_count(h); | ||
3281 | return rc; | ||
3247 | case CCISS_BIG_PASSTHRU: | 3282 | case CCISS_BIG_PASSTHRU: |
3248 | return hpsa_big_passthru_ioctl(h, argp); | 3283 | if (increment_passthru_count(h)) |
3284 | return -EAGAIN; | ||
3285 | rc = hpsa_big_passthru_ioctl(h, argp); | ||
3286 | decrement_passthru_count(h); | ||
3287 | return rc; | ||
3249 | default: | 3288 | default: |
3250 | return -ENOTTY; | 3289 | return -ENOTTY; |
3251 | } | 3290 | } |
@@ -4835,6 +4874,7 @@ reinit_after_soft_reset: | |||
4835 | INIT_LIST_HEAD(&h->reqQ); | 4874 | INIT_LIST_HEAD(&h->reqQ); |
4836 | spin_lock_init(&h->lock); | 4875 | spin_lock_init(&h->lock); |
4837 | spin_lock_init(&h->scan_lock); | 4876 | spin_lock_init(&h->scan_lock); |
4877 | spin_lock_init(&h->passthru_count_lock); | ||
4838 | rc = hpsa_pci_init(h); | 4878 | rc = hpsa_pci_init(h); |
4839 | if (rc != 0) | 4879 | if (rc != 0) |
4840 | goto clean1; | 4880 | goto clean1; |