vfs_bio.c (109554) | vfs_bio.c (109572) |
---|---|
1/* 2 * Copyright (c) 1994,1997 John S. Dyson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice immediately at the beginning of the file, without modification, 10 * this list of conditions, and the following disclaimer. 11 * 2. Absolutely no warranty of function or purpose is made by the author 12 * John S. Dyson. 13 * | 1/* 2 * Copyright (c) 1994,1997 John S. Dyson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice immediately at the beginning of the file, without modification, 10 * this list of conditions, and the following disclaimer. 11 * 2. Absolutely no warranty of function or purpose is made by the author 12 * John S. Dyson. 13 * |
14 * $FreeBSD: head/sys/kern/vfs_bio.c 109554 2003-01-20 09:24:03Z alc $ | 14 * $FreeBSD: head/sys/kern/vfs_bio.c 109572 2003-01-20 17:46:48Z dillon $ |
15 */ 16 17/* 18 * this file contains a new buffer I/O scheme implementing a coherent 19 * VM object and buffer cache scheme. Pains have been taken to make 20 * sure that the performance degradation associated with schemes such 21 * as this is not realized. 22 * --- 3519 unchanged lines hidden (view full) --- 3542} 3543 3544/* 3545 * Map an IO request into kernel virtual address space. 3546 * 3547 * All requests are (re)mapped into kernel VA space. 3548 * Notice that we use b_bufsize for the size of the buffer 3549 * to be mapped. b_bcount might be modified by the driver. | 15 */ 16 17/* 18 * this file contains a new buffer I/O scheme implementing a coherent 19 * VM object and buffer cache scheme. Pains have been taken to make 20 * sure that the performance degradation associated with schemes such 21 * as this is not realized. 22 * --- 3519 unchanged lines hidden (view full) --- 3542} 3543 3544/* 3545 * Map an IO request into kernel virtual address space. 3546 * 3547 * All requests are (re)mapped into kernel VA space. 3548 * Notice that we use b_bufsize for the size of the buffer 3549 * to be mapped. b_bcount might be modified by the driver. |
3550 * 3551 * Note that even if the caller determines that the address space should 3552 * be valid, a race or a smaller-file mapped into a larger space may 3553 * actually cause vmapbuf() to fail, so all callers of vmapbuf() MUST 3554 * check the return value. |
|
3550 */ | 3555 */ |
3551void | 3556int |
3552vmapbuf(struct buf *bp) 3553{ 3554 caddr_t addr, kva; 3555 vm_offset_t pa; | 3557vmapbuf(struct buf *bp) 3558{ 3559 caddr_t addr, kva; 3560 vm_offset_t pa; |
3556 int pidx; | 3561 int pidx, i; |
3557 struct vm_page *m; 3558 struct pmap *pmap = &curproc->p_vmspace->vm_pmap; 3559 3560 GIANT_REQUIRED; 3561 3562 if ((bp->b_flags & B_PHYS) == 0) 3563 panic("vmapbuf"); 3564 3565 for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0; 3566 addr < bp->b_data + bp->b_bufsize; 3567 addr += PAGE_SIZE, pidx++) { 3568 /* 3569 * Do the vm_fault if needed; do the copy-on-write thing 3570 * when reading stuff off device into memory. 3571 * 3572 * NOTE! Must use pmap_extract() because addr may be in 3573 * the userland address space, and kextract is only guarenteed 3574 * to work for the kernland address space (see: sparc64 port). 3575 */ | 3562 struct vm_page *m; 3563 struct pmap *pmap = &curproc->p_vmspace->vm_pmap; 3564 3565 GIANT_REQUIRED; 3566 3567 if ((bp->b_flags & B_PHYS) == 0) 3568 panic("vmapbuf"); 3569 3570 for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0; 3571 addr < bp->b_data + bp->b_bufsize; 3572 addr += PAGE_SIZE, pidx++) { 3573 /* 3574 * Do the vm_fault if needed; do the copy-on-write thing 3575 * when reading stuff off device into memory. 3576 * 3577 * NOTE! Must use pmap_extract() because addr may be in 3578 * the userland address space, and kextract is only guarenteed 3579 * to work for the kernland address space (see: sparc64 port). 3580 */ |
3576 vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data, 3577 (bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); | 3581retry: 3582 i = vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data, 3583 (bp->b_iocmd == BIO_READ) ? 3584 (VM_PROT_READ|VM_PROT_WRITE) : VM_PROT_READ); 3585 if (i < 0) { 3586 printf("vmapbuf: warning, bad user address during I/O\n"); 3587 vm_page_lock_queues(); 3588 for (i = 0; i < pidx; ++i) { 3589 vm_page_unhold(bp->b_pages[i]); 3590 bp->b_pages[i] = NULL; 3591 } 3592 vm_page_unlock_queues(); 3593 return(-1); 3594 } |
3578 pa = trunc_page(pmap_extract(pmap, (vm_offset_t) addr)); | 3595 pa = trunc_page(pmap_extract(pmap, (vm_offset_t) addr)); |
3579 if (pa == 0) 3580 panic("vmapbuf: page not present"); | 3596 if (pa == 0) { 3597 printf("vmapbuf: warning, race against user address during I/O"); 3598 goto retry; 3599 } |
3581 m = PHYS_TO_VM_PAGE(pa); 3582 vm_page_lock_queues(); 3583 vm_page_hold(m); 3584 vm_page_unlock_queues(); 3585 bp->b_pages[pidx] = m; 3586 } 3587 if (pidx > btoc(MAXPHYS)) 3588 panic("vmapbuf: mapped more than MAXPHYS"); 3589 pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx); 3590 3591 kva = bp->b_saveaddr; 3592 bp->b_npages = pidx; 3593 bp->b_saveaddr = bp->b_data; 3594 bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); | 3600 m = PHYS_TO_VM_PAGE(pa); 3601 vm_page_lock_queues(); 3602 vm_page_hold(m); 3603 vm_page_unlock_queues(); 3604 bp->b_pages[pidx] = m; 3605 } 3606 if (pidx > btoc(MAXPHYS)) 3607 panic("vmapbuf: mapped more than MAXPHYS"); 3608 pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx); 3609 3610 kva = bp->b_saveaddr; 3611 bp->b_npages = pidx; 3612 bp->b_saveaddr = bp->b_data; 3613 bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); |
3614 return(0); |
|
3595} 3596 3597/* 3598 * Free the io map PTEs associated with this IO operation. 3599 * We also invalidate the TLB entries and restore the original b_addr. 3600 */ 3601void 3602vunmapbuf(struct buf *bp) --- 57 unchanged lines hidden --- | 3615} 3616 3617/* 3618 * Free the io map PTEs associated with this IO operation. 3619 * We also invalidate the TLB entries and restore the original b_addr. 3620 */ 3621void 3622vunmapbuf(struct buf *bp) --- 57 unchanged lines hidden --- |