Implement write combining for crashdumps. This is useful when

write caching is disabled on both SCSI and IDE disks where large
memory dumps could take up to an hour to complete.

Taking an i386 scsi based system with 512MB of ram and timing (in
seconds) how long it took to complete a dump, the following results
were obtained:

Before:				After:
	WCE           TIME		WCE           TIME
	------------------		------------------
	1	141.820972		1	 15.600111
	0	797.265072		0	 65.480465

Obtained from:	Yahoo!
Reviewed by:	peter
This commit is contained in:
Paul Saab 2000-10-17 10:05:49 +00:00
parent 0eed4af9fa
commit c794ceb56a
10 changed files with 73 additions and 29 deletions

View File

@ -2223,9 +2223,9 @@ retry:
* during dump. * during dump.
*/ */
void * void *
pmap_kenter_temporary(vm_offset_t pa) pmap_kenter_temporary(vm_offset_t pa, int i)
{ {
return (void *) ALPHA_PHYS_TO_K0SEG(pa); return (void *) ALPHA_PHYS_TO_K0SEG(pa - (i * PAGE_SIZE));
} }
#define MAX_INIT_PT (96) #define MAX_INIT_PT (96)

View File

@ -107,6 +107,7 @@
#endif #endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ #define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */ #define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define CLSIZE 1 #define CLSIZE 1
#define CLSIZELOG2 0 #define CLSIZELOG2 0

View File

@ -182,6 +182,12 @@ static caddr_t CADDR2;
static pt_entry_t *msgbufmap; static pt_entry_t *msgbufmap;
struct msgbuf *msgbufp=0; struct msgbuf *msgbufp=0;
/*
* Crashdump maps.
*/
static pt_entry_t *pt_crashdumpmap;
static caddr_t crashdumpmap;
#ifdef SMP #ifdef SMP
extern pt_entry_t *SMPpt; extern pt_entry_t *SMPpt;
#else #else
@ -333,6 +339,11 @@ pmap_bootstrap(firstaddr, loadaddr)
SYSMAP(caddr_t, CMAP1, CADDR1, 1) SYSMAP(caddr_t, CMAP1, CADDR1, 1)
SYSMAP(caddr_t, CMAP2, CADDR2, 1) SYSMAP(caddr_t, CMAP2, CADDR2, 1)
/*
* Crashdump maps.
*/
SYSMAP(caddr_t, pt_crashdumpmap, crashdumpmap, MAXDUMPPGS);
/* /*
* ptvmmap is used for reading arbitrary physical pages via /dev/mem. * ptvmmap is used for reading arbitrary physical pages via /dev/mem.
* XXX ptmmap is not used. * XXX ptmmap is not used.
@ -2231,10 +2242,10 @@ retry:
* to be used for panic dumps. * to be used for panic dumps.
*/ */
void * void *
pmap_kenter_temporary(vm_offset_t pa) pmap_kenter_temporary(vm_offset_t pa, int i)
{ {
pmap_kenter((vm_offset_t)CADDR1, pa); pmap_kenter((vm_offset_t)crashdumpmap + (i * PAGE_SIZE), pa);
return ((void *)CADDR1); return ((void *)crashdumpmap);
} }
#define MAX_INIT_PT (96) #define MAX_INIT_PT (96)

View File

@ -634,7 +634,9 @@ dadump(dev_t dev)
long blkcnt; long blkcnt;
vm_offset_t addr; vm_offset_t addr;
struct ccb_scsiio csio; struct ccb_scsiio csio;
int dumppages = MAXDUMPPGS;
int error; int error;
int i;
/* toss any characters present prior to dump */ /* toss any characters present prior to dump */
while (cncheckc() != -1) while (cncheckc() != -1)
@ -659,12 +661,17 @@ dadump(dev_t dev)
blkcnt = howmany(PAGE_SIZE, secsize); blkcnt = howmany(PAGE_SIZE, secsize);
while (num > 0) { while (num > 0) {
void *va; caddr_t va;
if (is_physical_memory(addr)) { if ((num / blkcnt) < dumppages)
va = pmap_kenter_temporary(trunc_page(addr)); dumppages = num / blkcnt;
} else {
va = pmap_kenter_temporary(trunc_page(0)); for (i = 0; i < dumppages; ++i) {
vm_offset_t a = addr + (i * PAGE_SIZE);
if (is_physical_memory(a))
va = pmap_kenter_temporary(trunc_page(a), i);
else
va = pmap_kenter_temporary(trunc_page(0), i);
} }
xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
@ -677,9 +684,9 @@ dadump(dev_t dev)
/*byte2*/0, /*byte2*/0,
/*minimum_cmd_size*/ softc->minimum_cmd_size, /*minimum_cmd_size*/ softc->minimum_cmd_size,
blknum, blknum,
blkcnt, blkcnt * dumppages,
/*data_ptr*/(u_int8_t *) va, /*data_ptr*/(u_int8_t *) va,
/*dxfer_len*/blkcnt * secsize, /*dxfer_len*/blkcnt * secsize * dumppages,
/*sense_len*/SSD_FULL_SIZE, /*sense_len*/SSD_FULL_SIZE,
DA_DEFAULT_TIMEOUT * 1000); DA_DEFAULT_TIMEOUT * 1000);
xpt_polled_action((union ccb *)&csio); xpt_polled_action((union ccb *)&csio);
@ -706,9 +713,9 @@ dadump(dev_t dev)
} }
/* update block count */ /* update block count */
num -= blkcnt; num -= blkcnt * dumppages;
blknum += blkcnt; blknum += blkcnt * dumppages;
addr += PAGE_SIZE; addr += PAGE_SIZE * dumppages;
/* operator aborting dump? */ /* operator aborting dump? */
if (cncheckc() != -1) if (cncheckc() != -1)

View File

@ -257,7 +257,10 @@ addump(dev_t dev)
struct ad_request request; struct ad_request request;
u_int count, blkno, secsize; u_int count, blkno, secsize;
vm_offset_t addr = 0; vm_offset_t addr = 0;
long blkcnt;
int dumppages = MAXDUMPPGS;
int error; int error;
int i;
if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
return error; return error;
@ -269,18 +272,27 @@ addump(dev_t dev)
adp->controller->mode[ATA_DEV(adp->unit)] = ATA_PIO; adp->controller->mode[ATA_DEV(adp->unit)] = ATA_PIO;
ata_reinit(adp->controller); ata_reinit(adp->controller);
blkcnt = howmany(PAGE_SIZE, secsize);
while (count > 0) { while (count > 0) {
caddr_t va; caddr_t va;
DELAY(1000); DELAY(1000);
if (is_physical_memory(addr))
va = pmap_kenter_temporary(trunc_page(addr)); if ((count / blkcnt) < dumppages)
dumppages = count / blkcnt;
for (i = 0; i < dumppages; ++i) {
vm_offset_t a = addr + (i * PAGE_SIZE);
if (is_physical_memory(a))
va = pmap_kenter_temporary(trunc_page(a), i);
else else
va = pmap_kenter_temporary(trunc_page(0)); va = pmap_kenter_temporary(trunc_page(0), i);
}
bzero(&request, sizeof(struct ad_request)); bzero(&request, sizeof(struct ad_request));
request.device = adp; request.device = adp;
request.blockaddr = blkno; request.blockaddr = blkno;
request.bytecount = PAGE_SIZE; request.bytecount = PAGE_SIZE * dumppages;
request.data = va; request.data = va;
while (request.bytecount > 0) { while (request.bytecount > 0) {
@ -300,9 +312,9 @@ addump(dev_t dev)
printf("%ld ", (long)(count * DEV_BSIZE) / (1024 * 1024)); printf("%ld ", (long)(count * DEV_BSIZE) / (1024 * 1024));
} }
blkno += howmany(PAGE_SIZE, secsize); blkno += blkcnt * dumppages;
count -= howmany(PAGE_SIZE, secsize); count -= blkcnt * dumppages;
addr += PAGE_SIZE; addr += PAGE_SIZE * dumppages;
if (cncheckc() != -1) if (cncheckc() != -1)
return EINTR; return EINTR;
} }

View File

@ -182,6 +182,12 @@ static caddr_t CADDR2;
static pt_entry_t *msgbufmap; static pt_entry_t *msgbufmap;
struct msgbuf *msgbufp=0; struct msgbuf *msgbufp=0;
/*
* Crashdump maps.
*/
static pt_entry_t *pt_crashdumpmap;
static caddr_t crashdumpmap;
#ifdef SMP #ifdef SMP
extern pt_entry_t *SMPpt; extern pt_entry_t *SMPpt;
#else #else
@ -333,6 +339,11 @@ pmap_bootstrap(firstaddr, loadaddr)
SYSMAP(caddr_t, CMAP1, CADDR1, 1) SYSMAP(caddr_t, CMAP1, CADDR1, 1)
SYSMAP(caddr_t, CMAP2, CADDR2, 1) SYSMAP(caddr_t, CMAP2, CADDR2, 1)
/*
* Crashdump maps.
*/
SYSMAP(caddr_t, pt_crashdumpmap, crashdumpmap, MAXDUMPPGS);
/* /*
* ptvmmap is used for reading arbitrary physical pages via /dev/mem. * ptvmmap is used for reading arbitrary physical pages via /dev/mem.
* XXX ptmmap is not used. * XXX ptmmap is not used.
@ -2231,10 +2242,10 @@ retry:
* to be used for panic dumps. * to be used for panic dumps.
*/ */
void * void *
pmap_kenter_temporary(vm_offset_t pa) pmap_kenter_temporary(vm_offset_t pa, int i)
{ {
pmap_kenter((vm_offset_t)CADDR1, pa); pmap_kenter((vm_offset_t)crashdumpmap + (i * PAGE_SIZE), pa);
return ((void *)CADDR1); return ((void *)crashdumpmap);
} }
#define MAX_INIT_PT (96) #define MAX_INIT_PT (96)

View File

@ -96,6 +96,7 @@
#endif #endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ #define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */ #define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define IOPAGES 2 /* pages of i/o permission bitmap */ #define IOPAGES 2 /* pages of i/o permission bitmap */
#define UPAGES 2 /* pages of u-area */ #define UPAGES 2 /* pages of u-area */

View File

@ -1478,9 +1478,9 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m)
* during dump. * during dump.
*/ */
void * void *
pmap_kenter_temporary(vm_offset_t pa) pmap_kenter_temporary(vm_offset_t pa, int i)
{ {
return (void *) IA64_PHYS_TO_RR7(pa); return (void *) IA64_PHYS_TO_RR7(pa - (i * PAGE_SIZE));
} }
#define MAX_INIT_PT (96) #define MAX_INIT_PT (96)

View File

@ -103,6 +103,7 @@
#endif #endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ #define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */ #define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define CLSIZE 1 #define CLSIZE 1
#define CLSIZELOG2 0 #define CLSIZELOG2 0

View File

@ -140,7 +140,7 @@ void pmap_swapout_proc __P((struct proc *p));
void pmap_swapin_proc __P((struct proc *p)); void pmap_swapin_proc __P((struct proc *p));
void pmap_activate __P((struct proc *p)); void pmap_activate __P((struct proc *p));
vm_offset_t pmap_addr_hint __P((vm_object_t obj, vm_offset_t addr, vm_size_t size)); vm_offset_t pmap_addr_hint __P((vm_object_t obj, vm_offset_t addr, vm_size_t size));
void *pmap_kenter_temporary __P((vm_offset_t pa)); void *pmap_kenter_temporary __P((vm_offset_t pa, int i));
void pmap_init2 __P((void)); void pmap_init2 __P((void));
#endif /* _KERNEL */ #endif /* _KERNEL */