svn commit: r255922 - stable/9/sys/cam/ctl
Kenneth D. Merry
ken at FreeBSD.org
Sat Sep 28 05:56:38 UTC 2013
Author: ken
Date: Sat Sep 28 05:56:37 2013
New Revision: 255922
URL: http://svnweb.freebsd.org/changeset/base/255922
Log:
MFC 244015:
------------------------------------------------------------------------
r244015 | ken | 2012-12-07 21:16:07 -0700 (Fri, 07 Dec 2012) | 17 lines
Fix the CTL OOA queue dumping code so that it does not hold a mutex
while doing a copyout. That can cause a panic, because copyout
can trigger VM faults, and we can't handle VM faults while holding
a mutex.
The solution here is to malloc a separate buffer to hold the OOA
queue entries, so that we don't risk a VM fault while filling up
the buffer and we don't have to drop the lock. The other solution
would be to wire the user's memory while filling their buffer with
copyout, but that would have been a little more complex.
Also fix a debugging parenthesis issue in ctl_abort_task() pointed
out by Chuck Tuffli.
Sponsored by: Spectra Logic Corporation
Modified:
stable/9/sys/cam/ctl/ctl.c
Modified: stable/9/sys/cam/ctl/ctl.c
==============================================================================
--- stable/9/sys/cam/ctl/ctl.c Sat Sep 28 02:13:59 2013 (r255921)
+++ stable/9/sys/cam/ctl/ctl.c Sat Sep 28 05:56:37 2013 (r255922)
@@ -352,7 +352,8 @@ static void ctl_ioctl_hard_startstop_cal
struct cfi_metatask *metatask);
static void ctl_ioctl_bbrread_callback(void *arg,struct cfi_metatask *metatask);
static int ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num,
- struct ctl_ooa *ooa_hdr);
+ struct ctl_ooa *ooa_hdr,
+ struct ctl_ooa_entry *kern_entries);
static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td);
uint32_t ctl_get_resindex(struct ctl_nexus *nexus);
@@ -1982,7 +1983,7 @@ ctl_ioctl_bbrread_callback(void *arg, st
*/
static int
ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num,
- struct ctl_ooa *ooa_hdr)
+ struct ctl_ooa *ooa_hdr, struct ctl_ooa_entry *kern_entries)
{
union ctl_io *io;
int retval;
@@ -1992,7 +1993,7 @@ ctl_ioctl_fill_ooa(struct ctl_lun *lun,
for (io = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); (io != NULL);
(*cur_fill_num)++, io = (union ctl_io *)TAILQ_NEXT(&io->io_hdr,
ooa_links)) {
- struct ctl_ooa_entry *cur_entry, entry;
+ struct ctl_ooa_entry *entry;
/*
* If we've got more than we can fit, just count the
@@ -2001,36 +2002,29 @@ ctl_ioctl_fill_ooa(struct ctl_lun *lun,
if (*cur_fill_num >= ooa_hdr->alloc_num)
continue;
- cur_entry = &ooa_hdr->entries[*cur_fill_num];
+ entry = &kern_entries[*cur_fill_num];
- bzero(&entry, sizeof(entry));
-
- entry.tag_num = io->scsiio.tag_num;
- entry.lun_num = lun->lun;
+ entry->tag_num = io->scsiio.tag_num;
+ entry->lun_num = lun->lun;
#ifdef CTL_TIME_IO
- entry.start_bt = io->io_hdr.start_bt;
+ entry->start_bt = io->io_hdr.start_bt;
#endif
- bcopy(io->scsiio.cdb, entry.cdb, io->scsiio.cdb_len);
- entry.cdb_len = io->scsiio.cdb_len;
+ bcopy(io->scsiio.cdb, entry->cdb, io->scsiio.cdb_len);
+ entry->cdb_len = io->scsiio.cdb_len;
if (io->io_hdr.flags & CTL_FLAG_BLOCKED)
- entry.cmd_flags |= CTL_OOACMD_FLAG_BLOCKED;
+ entry->cmd_flags |= CTL_OOACMD_FLAG_BLOCKED;
if (io->io_hdr.flags & CTL_FLAG_DMA_INPROG)
- entry.cmd_flags |= CTL_OOACMD_FLAG_DMA;
+ entry->cmd_flags |= CTL_OOACMD_FLAG_DMA;
if (io->io_hdr.flags & CTL_FLAG_ABORT)
- entry.cmd_flags |= CTL_OOACMD_FLAG_ABORT;
+ entry->cmd_flags |= CTL_OOACMD_FLAG_ABORT;
if (io->io_hdr.flags & CTL_FLAG_IS_WAS_ON_RTR)
- entry.cmd_flags |= CTL_OOACMD_FLAG_RTR;
+ entry->cmd_flags |= CTL_OOACMD_FLAG_RTR;
if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED)
- entry.cmd_flags |= CTL_OOACMD_FLAG_DMA_QUEUED;
-
- retval = copyout(&entry, cur_entry, sizeof(entry));
-
- if (retval != 0)
- break;
+ entry->cmd_flags |= CTL_OOACMD_FLAG_DMA_QUEUED;
}
return (retval);
@@ -2433,6 +2427,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd,
case CTL_GET_OOA: {
struct ctl_lun *lun;
struct ctl_ooa *ooa_hdr;
+ struct ctl_ooa_entry *entries;
uint32_t cur_fill_num;
ooa_hdr = (struct ctl_ooa *)addr;
@@ -2456,11 +2451,20 @@ ctl_ioctl(struct cdev *dev, u_long cmd,
break;
}
+ entries = malloc(ooa_hdr->alloc_len, M_CTL, M_WAITOK | M_ZERO);
+ if (entries == NULL) {
+ printf("%s: could not allocate %d bytes for OOA "
+ "dump\n", __func__, ooa_hdr->alloc_len);
+ retval = ENOMEM;
+ break;
+ }
+
mtx_lock(&softc->ctl_lock);
if (((ooa_hdr->flags & CTL_OOA_FLAG_ALL_LUNS) == 0)
&& ((ooa_hdr->lun_num > CTL_MAX_LUNS)
|| (softc->ctl_luns[ooa_hdr->lun_num] == NULL))) {
mtx_unlock(&softc->ctl_lock);
+ free(entries, M_CTL);
printf("%s: CTL_GET_OOA: invalid LUN %ju\n",
__func__, (uintmax_t)ooa_hdr->lun_num);
retval = EINVAL;
@@ -2472,24 +2476,31 @@ ctl_ioctl(struct cdev *dev, u_long cmd,
if (ooa_hdr->flags & CTL_OOA_FLAG_ALL_LUNS) {
STAILQ_FOREACH(lun, &softc->lun_list, links) {
retval = ctl_ioctl_fill_ooa(lun, &cur_fill_num,
- ooa_hdr);
+ ooa_hdr, entries);
if (retval != 0)
break;
}
if (retval != 0) {
mtx_unlock(&softc->ctl_lock);
+ free(entries, M_CTL);
break;
}
} else {
lun = softc->ctl_luns[ooa_hdr->lun_num];
- retval = ctl_ioctl_fill_ooa(lun, &cur_fill_num,ooa_hdr);
+ retval = ctl_ioctl_fill_ooa(lun, &cur_fill_num,ooa_hdr,
+ entries);
}
mtx_unlock(&softc->ctl_lock);
ooa_hdr->fill_num = min(cur_fill_num, ooa_hdr->alloc_num);
ooa_hdr->fill_len = ooa_hdr->fill_num *
sizeof(struct ctl_ooa_entry);
+ retval = copyout(entries, ooa_hdr->entries, ooa_hdr->fill_len);
+ if (retval != 0) {
+ printf("%s: error copying out %d bytes for OOA dump\n",
+ __func__, ooa_hdr->fill_len);
+ }
getbintime(&ooa_hdr->cur_bt);
@@ -2500,6 +2511,8 @@ ctl_ioctl(struct cdev *dev, u_long cmd,
ooa_hdr->dropped_num = 0;
ooa_hdr->status = CTL_OOA_OK;
}
+
+ free(entries, M_CTL);
break;
}
case CTL_CHECK_OOA: {
@@ -10824,9 +10837,9 @@ ctl_abort_task(union ctl_io *io)
(xio->io_hdr.flags &
CTL_FLAG_DMA_INPROG) ? " DMA" : "",
(xio->io_hdr.flags &
- CTL_FLAG_ABORT) ? " ABORT" : ""),
+ CTL_FLAG_ABORT) ? " ABORT" : "",
(xio->io_hdr.flags &
- CTL_FLAG_IS_WAS_ON_RTR ? " RTR" : "");
+ CTL_FLAG_IS_WAS_ON_RTR ? " RTR" : ""));
ctl_scsi_command_string(&xio->scsiio, NULL, &sb);
sbuf_finish(&sb);
printf("%s\n", sbuf_data(&sb));
More information about the svn-src-stable-9
mailing list