nfs_bio.c (45361) | nfs_bio.c (46349) |
---|---|
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 | 1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 |
37 * $Id: nfs_bio.c,v 1.68 1999/04/05 19:38:28 julian Exp $ | 37 * $Id: nfs_bio.c,v 1.69 1999/04/06 03:07:54 peter Exp $ |
38 */ 39 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/resourcevar.h> 44#include <sys/signalvar.h> 45#include <sys/proc.h> --- 14 unchanged lines hidden (view full) --- 60#include <nfs/nfsproto.h> 61#include <nfs/nfs.h> 62#include <nfs/nfsmount.h> 63#include <nfs/nqnfs.h> 64#include <nfs/nfsnode.h> 65 66static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size, 67 struct proc *p)); | 38 */ 39 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/resourcevar.h> 44#include <sys/signalvar.h> 45#include <sys/proc.h> --- 14 unchanged lines hidden (view full) --- 60#include <nfs/nfsproto.h> 61#include <nfs/nfs.h> 62#include <nfs/nfsmount.h> 63#include <nfs/nqnfs.h> 64#include <nfs/nfsnode.h> 65 66static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size, 67 struct proc *p)); |
68static void nfs_prot_buf __P((struct buf *bp, int off, int n)); | |
69 70extern int nfs_numasync; 71extern int nfs_pbuf_freecnt; 72extern struct nfsstats nfsstats; 73 74/* 75 * Vnode op for VM getpages. 76 */ 77int 78nfs_getpages(ap) 79 struct vop_getpages_args /* { 80 struct vnode *a_vp; 81 vm_page_t *a_m; 82 int a_count; 83 int a_reqpage; 84 vm_ooffset_t a_offset; 85 } */ *ap; 86{ | 68 69extern int nfs_numasync; 70extern int nfs_pbuf_freecnt; 71extern struct nfsstats nfsstats; 72 73/* 74 * Vnode op for VM getpages. 75 */ 76int 77nfs_getpages(ap) 78 struct vop_getpages_args /* { 79 struct vnode *a_vp; 80 vm_page_t *a_m; 81 int a_count; 82 int a_reqpage; 83 vm_ooffset_t a_offset; 84 } */ *ap; 85{ |
87 int i, error, nextoff, size, toff, npages, count; | 86 int i, error, nextoff, size, toff, count, npages; |
88 struct uio uio; 89 struct iovec iov; 90 vm_offset_t kva; 91 struct buf *bp; 92 struct vnode *vp; 93 struct proc *p; 94 struct ucred *cred; 95 struct nfsmount *nmp; --- 9 unchanged lines hidden (view full) --- 105 if (vp->v_object == NULL) { 106 printf("nfs_getpages: called with non-merged cache vnode??\n"); 107 return VM_PAGER_ERROR; 108 } 109 110 if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 && 111 (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) 112 (void)nfs_fsinfo(nmp, vp, cred, p); | 87 struct uio uio; 88 struct iovec iov; 89 vm_offset_t kva; 90 struct buf *bp; 91 struct vnode *vp; 92 struct proc *p; 93 struct ucred *cred; 94 struct nfsmount *nmp; --- 9 unchanged lines hidden (view full) --- 104 if (vp->v_object == NULL) { 105 printf("nfs_getpages: called with non-merged cache vnode??\n"); 106 return VM_PAGER_ERROR; 107 } 108 109 if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 && 110 (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) 111 (void)nfs_fsinfo(nmp, vp, cred, p); |
112 113 npages = btoc(count); 114 |
|
113 /* | 115 /* |
116 * If the requested page is partially valid, just return it and 117 * allow the pager to zero-out the blanks. Partially valid pages 118 * can only occur at the file EOF. 119 */ 120 121 { 122 vm_page_t m = pages[ap->a_reqpage]; 123 124 if (m->valid != 0) { 125 /* handled by vm_fault now */ 126 /* vm_page_zero_invalid(m, TRUE); */ 127 for (i = 0; i < npages; ++i) { 128 if (i != ap->a_reqpage) 129 vnode_pager_freepage(pages[i]); 130 } 131 return(0); 132 } 133 } 134 135 /* |
|
114 * We use only the kva address for the buffer, but this is extremely 115 * convienient and fast. 116 */ 117 bp = getpbuf(&nfs_pbuf_freecnt); 118 | 136 * We use only the kva address for the buffer, but this is extremely 137 * convienient and fast. 138 */ 139 bp = getpbuf(&nfs_pbuf_freecnt); 140 |
119 npages = btoc(count); | |
120 kva = (vm_offset_t) bp->b_data; 121 pmap_qenter(kva, pages, npages); 122 123 iov.iov_base = (caddr_t) kva; 124 iov.iov_len = count; 125 uio.uio_iov = &iov; 126 uio.uio_iovcnt = 1; 127 uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); --- 34 unchanged lines hidden (view full) --- 162 if (nextoff <= size) { 163 /* 164 * Read operation filled an entire page 165 */ 166 m->valid = VM_PAGE_BITS_ALL; 167 m->dirty = 0; 168 } else if (size > toff) { 169 /* | 141 kva = (vm_offset_t) bp->b_data; 142 pmap_qenter(kva, pages, npages); 143 144 iov.iov_base = (caddr_t) kva; 145 iov.iov_len = count; 146 uio.uio_iov = &iov; 147 uio.uio_iovcnt = 1; 148 uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); --- 34 unchanged lines hidden (view full) --- 183 if (nextoff <= size) { 184 /* 185 * Read operation filled an entire page 186 */ 187 m->valid = VM_PAGE_BITS_ALL; 188 m->dirty = 0; 189 } else if (size > toff) { 190 /* |
170 * Read operation filled a partial page, set valid 171 * bits properly. validclean will zero out 172 * any cruft in the buffer when setting a valid bit, 173 * if the size is not DEV_BSIZE aligned. | 191 * Read operation filled a partial page. |
174 */ | 192 */ |
193 m->valid = 0; |
|
175 vm_page_set_validclean(m, 0, size - toff); | 194 vm_page_set_validclean(m, 0, size - toff); |
195 /* handled by vm_fault now */ 196 /* vm_page_zero_invalid(m, TRUE); */ |
|
176 } 177 178 if (i != ap->a_reqpage) { 179 /* 180 * Whether or not to leave the page activated is up in 181 * the air, but we should put the page on a page queue 182 * somewhere (it already is in the object). Result: 183 * It appears that emperical results show that --- 8 unchanged lines hidden (view full) --- 192 if (m->flags & PG_WANTED) 193 vm_page_activate(m); 194 else 195 vm_page_deactivate(m); 196 vm_page_wakeup(m); 197 } else { 198 vnode_pager_freepage(m); 199 } | 197 } 198 199 if (i != ap->a_reqpage) { 200 /* 201 * Whether or not to leave the page activated is up in 202 * the air, but we should put the page on a page queue 203 * somewhere (it already is in the object). Result: 204 * It appears that emperical results show that --- 8 unchanged lines hidden (view full) --- 213 if (m->flags & PG_WANTED) 214 vm_page_activate(m); 215 else 216 vm_page_deactivate(m); 217 vm_page_wakeup(m); 218 } else { 219 vnode_pager_freepage(m); 220 } |
200 } else { 201 /* 202 * This page is being mapped, clear out any other 203 * cruft in the invalid areas of the page. 204 */ 205 if (m->valid && m->valid != VM_PAGE_BITS_ALL) 206 vm_page_zero_invalid(m, FALSE); | |
207 } 208 } 209 return 0; 210} 211 212/* 213 * Vnode op for VM putpages. 214 */ --- 8 unchanged lines hidden (view full) --- 223 vm_ooffset_t a_offset; 224 } */ *ap; 225{ 226 struct uio uio; 227 struct iovec iov; 228 vm_offset_t kva; 229 struct buf *bp; 230 int iomode, must_commit, i, error, npages, count; | 221 } 222 } 223 return 0; 224} 225 226/* 227 * Vnode op for VM putpages. 228 */ --- 8 unchanged lines hidden (view full) --- 237 vm_ooffset_t a_offset; 238 } */ *ap; 239{ 240 struct uio uio; 241 struct iovec iov; 242 vm_offset_t kva; 243 struct buf *bp; 244 int iomode, must_commit, i, error, npages, count; |
245 off_t offset; |
|
231 int *rtvals; 232 struct vnode *vp; 233 struct proc *p; 234 struct ucred *cred; 235 struct nfsmount *nmp; | 246 int *rtvals; 247 struct vnode *vp; 248 struct proc *p; 249 struct ucred *cred; 250 struct nfsmount *nmp; |
251 struct nfsnode *np; |
|
236 vm_page_t *pages; 237 238 vp = ap->a_vp; | 252 vm_page_t *pages; 253 254 vp = ap->a_vp; |
255 np = VTONFS(vp); |
|
239 p = curproc; /* XXX */ 240 cred = curproc->p_ucred; /* XXX */ 241 nmp = VFSTONFS(vp->v_mount); 242 pages = ap->a_m; 243 count = ap->a_count; 244 rtvals = ap->a_rtvals; 245 npages = btoc(count); | 256 p = curproc; /* XXX */ 257 cred = curproc->p_ucred; /* XXX */ 258 nmp = VFSTONFS(vp->v_mount); 259 pages = ap->a_m; 260 count = ap->a_count; 261 rtvals = ap->a_rtvals; 262 npages = btoc(count); |
263 offset = IDX_TO_OFF(pages[0]->pindex); |
|
246 247 if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 && 248 (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) 249 (void)nfs_fsinfo(nmp, vp, cred, p); 250 251 for (i = 0; i < npages; i++) { 252 rtvals[i] = VM_PAGER_AGAIN; 253 } 254 255 /* | 264 265 if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 && 266 (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) 267 (void)nfs_fsinfo(nmp, vp, cred, p); 268 269 for (i = 0; i < npages; i++) { 270 rtvals[i] = VM_PAGER_AGAIN; 271 } 272 273 /* |
274 * When putting pages, do not extend file past EOF. 275 */ 276 277 if (offset + count > np->n_size) { 278 count = np->n_size - offset; 279 if (count < 0) 280 count = 0; 281 } 282 283 /* |
|
256 * We use only the kva address for the buffer, but this is extremely 257 * convienient and fast. 258 */ 259 bp = getpbuf(&nfs_pbuf_freecnt); 260 261 kva = (vm_offset_t) bp->b_data; 262 pmap_qenter(kva, pages, npages); 263 264 iov.iov_base = (caddr_t) kva; 265 iov.iov_len = count; 266 uio.uio_iov = &iov; 267 uio.uio_iovcnt = 1; | 284 * We use only the kva address for the buffer, but this is extremely 285 * convienient and fast. 286 */ 287 bp = getpbuf(&nfs_pbuf_freecnt); 288 289 kva = (vm_offset_t) bp->b_data; 290 pmap_qenter(kva, pages, npages); 291 292 iov.iov_base = (caddr_t) kva; 293 iov.iov_len = count; 294 uio.uio_iov = &iov; 295 uio.uio_iovcnt = 1; |
268 uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); | 296 uio.uio_offset = offset; |
269 uio.uio_resid = count; 270 uio.uio_segflg = UIO_SYSSPACE; 271 uio.uio_rw = UIO_WRITE; 272 uio.uio_procp = p; 273 274 if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0) 275 iomode = NFSV3WRITE_UNSTABLE; 276 else --- 15 unchanged lines hidden (view full) --- 292 } 293 return rtvals[0]; 294} 295 296/* 297 * Vnode op for read using bio 298 */ 299int | 297 uio.uio_resid = count; 298 uio.uio_segflg = UIO_SYSSPACE; 299 uio.uio_rw = UIO_WRITE; 300 uio.uio_procp = p; 301 302 if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0) 303 iomode = NFSV3WRITE_UNSTABLE; 304 else --- 15 unchanged lines hidden (view full) --- 320 } 321 return rtvals[0]; 322} 323 324/* 325 * Vnode op for read using bio 326 */ 327int |
300nfs_bioread(vp, uio, ioflag, cred, getpages) | 328nfs_bioread(vp, uio, ioflag, cred) |
301 register struct vnode *vp; 302 register struct uio *uio; 303 int ioflag; 304 struct ucred *cred; | 329 register struct vnode *vp; 330 register struct uio *uio; 331 int ioflag; 332 struct ucred *cred; |
305 int getpages; | |
306{ 307 register struct nfsnode *np = VTONFS(vp); 308 register int biosize, i; | 333{ 334 register struct nfsnode *np = VTONFS(vp); 335 register int biosize, i; |
309 off_t diff; | |
310 struct buf *bp = 0, *rabp; 311 struct vattr vattr; 312 struct proc *p; 313 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 314 daddr_t lbn, rabn; | 336 struct buf *bp = 0, *rabp; 337 struct vattr vattr; 338 struct proc *p; 339 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 340 daddr_t lbn, rabn; |
315 int bufsize; 316 int nra, error = 0, n = 0, on = 0, not_readin; | 341 int bcount; 342 int nra, error = 0, n = 0, on = 0; |
317 318#ifdef DIAGNOSTIC 319 if (uio->uio_rw != UIO_READ) 320 panic("nfs_read mode"); 321#endif 322 if (uio->uio_resid == 0) 323 return (0); 324 if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */ --- 94 unchanged lines hidden (view full) --- 419 vp->v_type); 420 }; 421 } 422 switch (vp->v_type) { 423 case VREG: 424 nfsstats.biocache_reads++; 425 lbn = uio->uio_offset / biosize; 426 on = uio->uio_offset & (biosize - 1); | 343 344#ifdef DIAGNOSTIC 345 if (uio->uio_rw != UIO_READ) 346 panic("nfs_read mode"); 347#endif 348 if (uio->uio_resid == 0) 349 return (0); 350 if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */ --- 94 unchanged lines hidden (view full) --- 445 vp->v_type); 446 }; 447 } 448 switch (vp->v_type) { 449 case VREG: 450 nfsstats.biocache_reads++; 451 lbn = uio->uio_offset / biosize; 452 on = uio->uio_offset & (biosize - 1); |
427 not_readin = 1; | |
428 429 /* 430 * Start the read ahead(s), as required. 431 */ 432 if (nfs_numasync > 0 && nmp->nm_readahead > 0) { 433 for (nra = 0; nra < nmp->nm_readahead && 434 (off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) { 435 rabn = lbn + 1 + nra; 436 if (!incore(vp, rabn)) { 437 rabp = nfs_getcacheblk(vp, rabn, biosize, p); 438 if (!rabp) 439 return (EINTR); 440 if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { 441 rabp->b_flags |= (B_READ | B_ASYNC); | 453 454 /* 455 * Start the read ahead(s), as required. 456 */ 457 if (nfs_numasync > 0 && nmp->nm_readahead > 0) { 458 for (nra = 0; nra < nmp->nm_readahead && 459 (off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) { 460 rabn = lbn + 1 + nra; 461 if (!incore(vp, rabn)) { 462 rabp = nfs_getcacheblk(vp, rabn, biosize, p); 463 if (!rabp) 464 return (EINTR); 465 if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { 466 rabp->b_flags |= (B_READ | B_ASYNC); |
442 rabp->b_flags &= ~B_DONE; | |
443 vfs_busy_pages(rabp, 0); 444 if (nfs_asyncio(rabp, cred)) { 445 rabp->b_flags |= B_INVAL|B_ERROR; 446 vfs_unbusy_pages(rabp); 447 brelse(rabp); 448 } 449 } else 450 brelse(rabp); 451 } 452 } 453 } 454 455 /* | 467 vfs_busy_pages(rabp, 0); 468 if (nfs_asyncio(rabp, cred)) { 469 rabp->b_flags |= B_INVAL|B_ERROR; 470 vfs_unbusy_pages(rabp); 471 brelse(rabp); 472 } 473 } else 474 brelse(rabp); 475 } 476 } 477 } 478 479 /* |
456 * If the block is in the cache and has the required data 457 * in a valid region, just copy it out. 458 * Otherwise, get the block and write back/read in, 459 * as required. | 480 * Obtain the buffer cache block. Figure out the buffer size 481 * when we are at EOF. nfs_getcacheblk() will also force 482 * uncached delayed-writes to be flushed to the server. 483 * 484 * Note that bcount is *not* DEV_BSIZE aligned. |
460 */ | 485 */ |
461again: 462 bufsize = biosize; 463 if ((off_t)(lbn + 1) * biosize > np->n_size && 464 (off_t)(lbn + 1) * biosize - np->n_size < biosize) { 465 bufsize = np->n_size - (off_t)lbn * biosize; 466 bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); | 486 487 bcount = biosize; 488 if ((off_t)lbn * biosize >= np->n_size) { 489 bcount = 0; 490 } else if ((off_t)(lbn + 1) * biosize > np->n_size) { 491 bcount = np->n_size - (off_t)lbn * biosize; |
467 } | 492 } |
468 bp = nfs_getcacheblk(vp, lbn, bufsize, p); | 493 494 bp = nfs_getcacheblk(vp, lbn, bcount, p); |
469 if (!bp) 470 return (EINTR); 471 472 /* | 495 if (!bp) 496 return (EINTR); 497 498 /* |
473 * If we are being called from nfs_getpages, we must 474 * make sure the buffer is a vmio buffer. The vp will 475 * already be setup for vmio but there may be some old 476 * non-vmio buffers attached to it. | 499 * If B_CACHE is not set, we must issue the read. If this 500 * fails, we return an error. |
477 */ | 501 */ |
478 if (getpages && !(bp->b_flags & B_VMIO)) { 479#ifdef DIAGNOSTIC 480 printf("nfs_bioread: non vmio buf found, discarding\n"); 481#endif 482 bp->b_flags |= B_NOCACHE; 483 bp->b_flags |= B_INVAFTERWRITE; 484 if (bp->b_dirtyend > 0) { 485 if ((bp->b_flags & B_DELWRI) == 0) 486 panic("nfsbioread"); 487 if (VOP_BWRITE(bp) == EINTR) 488 return (EINTR); 489 } else 490 brelse(bp); 491 goto again; 492 } | 502 |
493 if ((bp->b_flags & B_CACHE) == 0) { 494 bp->b_flags |= B_READ; | 503 if ((bp->b_flags & B_CACHE) == 0) { 504 bp->b_flags |= B_READ; |
495 bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL); 496 not_readin = 0; | |
497 vfs_busy_pages(bp, 0); 498 error = nfs_doio(bp, cred, p); 499 if (error) { 500 brelse(bp); 501 return (error); 502 } 503 } | 505 vfs_busy_pages(bp, 0); 506 error = nfs_doio(bp, cred, p); 507 if (error) { 508 brelse(bp); 509 return (error); 510 } 511 } |
504 if (bufsize > on) { 505 n = min((unsigned)(bufsize - on), uio->uio_resid); 506 } else { 507 n = 0; 508 } 509 diff = np->n_size - uio->uio_offset; 510 if (diff < n) 511 n = diff; 512 if (not_readin && n > 0) { 513 if (on < bp->b_validoff || (on + n) > bp->b_validend) { 514 bp->b_flags |= B_NOCACHE; 515 bp->b_flags |= B_INVAFTERWRITE; 516 if (bp->b_dirtyend > 0) { 517 if ((bp->b_flags & B_DELWRI) == 0) 518 panic("nfsbioread"); 519 if (VOP_BWRITE(bp) == EINTR) 520 return (EINTR); 521 } else 522 brelse(bp); 523 goto again; 524 } 525 } | 512 513 /* 514 * on is the offset into the current bp. Figure out how many 515 * bytes we can copy out of the bp. Note that bcount is 516 * NOT DEV_BSIZE aligned. 517 * 518 * Then figure out how many bytes we can copy into the uio. 519 */ 520 521 n = 0; 522 if (on < bcount) 523 n = min((unsigned)(bcount - on), uio->uio_resid); 524 |
526 vp->v_lastr = lbn; | 525 vp->v_lastr = lbn; |
527 diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on); 528 if (diff < n) 529 n = diff; | |
530 break; 531 case VLNK: 532 nfsstats.biocache_readlinks++; 533 bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, p); 534 if (!bp) 535 return (EINTR); 536 if ((bp->b_flags & B_CACHE) == 0) { 537 bp->b_flags |= B_READ; | 526 break; 527 case VLNK: 528 nfsstats.biocache_readlinks++; 529 bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, p); 530 if (!bp) 531 return (EINTR); 532 if ((bp->b_flags & B_CACHE) == 0) { 533 bp->b_flags |= B_READ; |
538 bp->b_flags &= ~B_DONE; | |
539 vfs_busy_pages(bp, 0); 540 error = nfs_doio(bp, cred, p); 541 if (error) { 542 bp->b_flags |= B_ERROR; 543 brelse(bp); 544 return (error); 545 } 546 } --- 8 unchanged lines hidden (view full) --- 555 } 556 lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; 557 on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); 558 bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p); 559 if (!bp) 560 return (EINTR); 561 if ((bp->b_flags & B_CACHE) == 0) { 562 bp->b_flags |= B_READ; | 534 vfs_busy_pages(bp, 0); 535 error = nfs_doio(bp, cred, p); 536 if (error) { 537 bp->b_flags |= B_ERROR; 538 brelse(bp); 539 return (error); 540 } 541 } --- 8 unchanged lines hidden (view full) --- 550 } 551 lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; 552 on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); 553 bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p); 554 if (!bp) 555 return (EINTR); 556 if ((bp->b_flags & B_CACHE) == 0) { 557 bp->b_flags |= B_READ; |
563 bp->b_flags &= ~B_DONE; | |
564 vfs_busy_pages(bp, 0); 565 error = nfs_doio(bp, cred, p); 566 if (error) { 567 brelse(bp); 568 } 569 while (error == NFSERR_BAD_COOKIE) { | 558 vfs_busy_pages(bp, 0); 559 error = nfs_doio(bp, cred, p); 560 if (error) { 561 brelse(bp); 562 } 563 while (error == NFSERR_BAD_COOKIE) { |
564 printf("got bad cookie vp %p bp %p\n", vp, bp); |
|
570 nfs_invaldir(vp); 571 error = nfs_vinvalbuf(vp, 0, cred, p, 1); 572 /* 573 * Yuck! The directory has been modified on the 574 * server. The only way to get the block is by 575 * reading from the beginning to get all the 576 * offset cookies. | 565 nfs_invaldir(vp); 566 error = nfs_vinvalbuf(vp, 0, cred, p, 1); 567 /* 568 * Yuck! The directory has been modified on the 569 * server. The only way to get the block is by 570 * reading from the beginning to get all the 571 * offset cookies. |
572 * 573 * Leave the last bp intact unless there is an error. 574 * Loop back up to the while if the error is another 575 * NFSERR_BAD_COOKIE (double yuch!). |
|
577 */ 578 for (i = 0; i <= lbn && !error; i++) { 579 if (np->n_direofoffset 580 && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset) 581 return (0); 582 bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p); 583 if (!bp) 584 return (EINTR); | 576 */ 577 for (i = 0; i <= lbn && !error; i++) { 578 if (np->n_direofoffset 579 && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset) 580 return (0); 581 bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p); 582 if (!bp) 583 return (EINTR); |
585 if ((bp->b_flags & B_DONE) == 0) { 586 bp->b_flags |= B_READ; 587 bp->b_flags &= ~B_DONE; 588 vfs_busy_pages(bp, 0); 589 error = nfs_doio(bp, cred, p); 590 if (error == 0 && (bp->b_flags & B_INVAL)) 591 break; 592 if (error) { 593 brelse(bp); 594 } else if (i < lbn) { 595 brelse(bp); 596 } | 584 if ((bp->b_flags & B_CACHE) == 0) { 585 bp->b_flags |= B_READ; 586 vfs_busy_pages(bp, 0); 587 error = nfs_doio(bp, cred, p); 588 /* 589 * no error + B_INVAL == directory EOF, 590 * use the block. 591 */ 592 if (error == 0 && (bp->b_flags & B_INVAL)) 593 break; |
597 } | 594 } |
595 /* 596 * An error will throw away the block and the 597 * for loop will break out. If no error and this 598 * is not the block we want, we throw away the 599 * block and go for the next one via the for loop. 600 */ 601 if (error || i < lbn) 602 brelse(bp); |
|
598 } 599 } | 603 } 604 } |
605 /* 606 * The above while is repeated if we hit another cookie 607 * error. If we hit an error and it wasn't a cookie error, 608 * we give up. 609 */ |
|
600 if (error) 601 return (error); 602 } 603 604 /* 605 * If not eof and read aheads are enabled, start one. 606 * (You need the current block first, so that you have the 607 * directory offset cookie of the next block.) 608 */ 609 if (nfs_numasync > 0 && nmp->nm_readahead > 0 && 610 (bp->b_flags & B_INVAL) == 0 && 611 (np->n_direofoffset == 0 || 612 (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) && 613 !(np->n_flag & NQNFSNONCACHE) && 614 !incore(vp, lbn + 1)) { 615 rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p); 616 if (rabp) { 617 if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { 618 rabp->b_flags |= (B_READ | B_ASYNC); | 610 if (error) 611 return (error); 612 } 613 614 /* 615 * If not eof and read aheads are enabled, start one. 616 * (You need the current block first, so that you have the 617 * directory offset cookie of the next block.) 618 */ 619 if (nfs_numasync > 0 && nmp->nm_readahead > 0 && 620 (bp->b_flags & B_INVAL) == 0 && 621 (np->n_direofoffset == 0 || 622 (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) && 623 !(np->n_flag & NQNFSNONCACHE) && 624 !incore(vp, lbn + 1)) { 625 rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p); 626 if (rabp) { 627 if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { 628 rabp->b_flags |= (B_READ | B_ASYNC); |
619 rabp->b_flags &= ~B_DONE; | |
620 vfs_busy_pages(rabp, 0); 621 if (nfs_asyncio(rabp, cred)) { 622 rabp->b_flags |= B_INVAL|B_ERROR; 623 vfs_unbusy_pages(rabp); 624 brelse(rabp); 625 } 626 } else { 627 brelse(rabp); 628 } 629 } 630 } 631 /* | 629 vfs_busy_pages(rabp, 0); 630 if (nfs_asyncio(rabp, cred)) { 631 rabp->b_flags |= B_INVAL|B_ERROR; 632 vfs_unbusy_pages(rabp); 633 brelse(rabp); 634 } 635 } else { 636 brelse(rabp); 637 } 638 } 639 } 640 /* |
632 * Make sure we use a signed variant of min() since 633 * the second term may be negative. | 641 * Unlike VREG files, whos buffer size ( bp->b_bcount ) is 642 * chopped for the EOF condition, we cannot tell how large 643 * NFS directories are going to be until we hit EOF. So 644 * an NFS directory buffer is *not* chopped to its EOF. Now, 645 * it just so happens that b_resid will effectively chop it 646 * to EOF. *BUT* this information is lost if the buffer goes 647 * away and is reconstituted into a B_CACHE state ( due to 648 * being VMIO ) later. So we keep track of the directory eof 649 * in np->n_direofoffset and chop it off as an extra step 650 * right here. |
634 */ 635 n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on); | 651 */ 652 n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on); |
653 if (np->n_direofoffset && n > np->n_direofoffset - uio->uio_offset) 654 n = np->n_direofoffset - uio->uio_offset; |
|
636 break; 637 default: 638 printf(" nfs_bioread: type %x unexpected\n",vp->v_type); 639 break; 640 }; 641 642 if (n > 0) { 643 error = uiomove(bp->b_data + on, (int)n, uio); 644 } 645 switch (vp->v_type) { 646 case VREG: 647 break; 648 case VLNK: 649 n = 0; 650 break; 651 case VDIR: | 655 break; 656 default: 657 printf(" nfs_bioread: type %x unexpected\n",vp->v_type); 658 break; 659 }; 660 661 if (n > 0) { 662 error = uiomove(bp->b_data + on, (int)n, uio); 663 } 664 switch (vp->v_type) { 665 case VREG: 666 break; 667 case VLNK: 668 n = 0; 669 break; 670 case VDIR: |
671 /* 672 * Invalidate buffer if caching is disabled, forcing a 673 * re-read from the remote later. 674 */ |
|
652 if (np->n_flag & NQNFSNONCACHE) 653 bp->b_flags |= B_INVAL; 654 break; 655 default: 656 printf(" nfs_bioread: type %x unexpected\n",vp->v_type); 657 } 658 brelse(bp); 659 } while (error == 0 && uio->uio_resid > 0 && n > 0); 660 return (error); 661} 662 | 675 if (np->n_flag & NQNFSNONCACHE) 676 bp->b_flags |= B_INVAL; 677 break; 678 default: 679 printf(" nfs_bioread: type %x unexpected\n",vp->v_type); 680 } 681 brelse(bp); 682 } while (error == 0 && uio->uio_resid > 0 && n > 0); 683 return (error); 684} 685 |
663static void 664nfs_prot_buf(bp, off, n) 665 struct buf *bp; 666 int off; 667 int n; 668{ 669 int pindex, boff, end; 670 671 if ((bp->b_flags & B_VMIO) == 0) 672 return; 673 674 end = round_page(off + n); 675 for (boff = trunc_page(off); boff < end; boff += PAGE_SIZE) { 676 pindex = boff >> PAGE_SHIFT; 677 vm_page_protect(bp->b_pages[pindex], VM_PROT_NONE); 678 } 679} 680 | |
681/* 682 * Vnode op for write using bio 683 */ 684int 685nfs_write(ap) 686 struct vop_write_args /* { 687 struct vnode *a_vp; 688 struct uio *a_uio; 689 int a_ioflag; 690 struct ucred *a_cred; 691 } */ *ap; 692{ | 686/* 687 * Vnode op for write using bio 688 */ 689int 690nfs_write(ap) 691 struct vop_write_args /* { 692 struct vnode *a_vp; 693 struct uio *a_uio; 694 int a_ioflag; 695 struct ucred *a_cred; 696 } */ *ap; 697{ |
693 register int biosize; 694 register struct uio *uio = ap->a_uio; | 698 int biosize; 699 struct uio *uio = ap->a_uio; |
695 struct proc *p = uio->uio_procp; | 700 struct proc *p = uio->uio_procp; |
696 register struct vnode *vp = ap->a_vp; | 701 struct vnode *vp = ap->a_vp; |
697 struct nfsnode *np = VTONFS(vp); | 702 struct nfsnode *np = VTONFS(vp); |
698 register struct ucred *cred = ap->a_cred; | 703 struct ucred *cred = ap->a_cred; |
699 int ioflag = ap->a_ioflag; 700 struct buf *bp; 701 struct vattr vattr; 702 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 703 daddr_t lbn; | 704 int ioflag = ap->a_ioflag; 705 struct buf *bp; 706 struct vattr vattr; 707 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 708 daddr_t lbn; |
704 int bufsize; | 709 int bcount; |
705 int n, on, error = 0, iomode, must_commit; 706 707#ifdef DIAGNOSTIC 708 if (uio->uio_rw != UIO_WRITE) 709 panic("nfs_write mode"); 710 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 711 panic("nfs_write proc"); 712#endif --- 31 unchanged lines hidden (view full) --- 744 * Maybe this should be above the vnode op call, but so long as 745 * file servers have no limits, i don't think it matters 746 */ 747 if (p && uio->uio_offset + uio->uio_resid > 748 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 749 psignal(p, SIGXFSZ); 750 return (EFBIG); 751 } | 710 int n, on, error = 0, iomode, must_commit; 711 712#ifdef DIAGNOSTIC 713 if (uio->uio_rw != UIO_WRITE) 714 panic("nfs_write mode"); 715 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 716 panic("nfs_write proc"); 717#endif --- 31 unchanged lines hidden (view full) --- 749 * Maybe this should be above the vnode op call, but so long as 750 * file servers have no limits, i don't think it matters 751 */ 752 if (p && uio->uio_offset + uio->uio_resid > 753 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 754 psignal(p, SIGXFSZ); 755 return (EFBIG); 756 } |
752 /* 753 * I use nm_rsize, not nm_wsize so that all buffer cache blocks 754 * will be the same size within a filesystem. nfs_writerpc will 755 * still use nm_wsize when sizing the rpc's. 756 */ | 757 |
757 biosize = vp->v_mount->mnt_stat.f_iosize; | 758 biosize = vp->v_mount->mnt_stat.f_iosize; |
759 |
|
758 do { 759 /* 760 * Check for a valid write lease. 761 */ 762 if ((nmp->nm_flag & NFSMNT_NQNFS) && 763 NQNFS_CKINVALID(vp, np, ND_WRITE)) { 764 do { 765 error = nqnfs_getlease(vp, ND_WRITE, cred, p); --- 15 unchanged lines hidden (view full) --- 781 nfs_clearcommit(vp->v_mount); 782 return (error); 783 } 784 nfsstats.biocache_writes++; 785 lbn = uio->uio_offset / biosize; 786 on = uio->uio_offset & (biosize-1); 787 n = min((unsigned)(biosize - on), uio->uio_resid); 788again: | 760 do { 761 /* 762 * Check for a valid write lease. 763 */ 764 if ((nmp->nm_flag & NFSMNT_NQNFS) && 765 NQNFS_CKINVALID(vp, np, ND_WRITE)) { 766 do { 767 error = nqnfs_getlease(vp, ND_WRITE, cred, p); --- 15 unchanged lines hidden (view full) --- 783 nfs_clearcommit(vp->v_mount); 784 return (error); 785 } 786 nfsstats.biocache_writes++; 787 lbn = uio->uio_offset / biosize; 788 on = uio->uio_offset & (biosize-1); 789 n = min((unsigned)(biosize - on), uio->uio_resid); 790again: |
789 if (uio->uio_offset + n > np->n_size) { | 791 /* 792 * Handle direct append and file extension cases, calculate 793 * unaligned buffer size. 794 */ 795 796 if (uio->uio_offset == np->n_size && n) { 797 /* 798 * special append case. Obtain buffer prior to 799 * resizing it to maintain B_CACHE. 800 */ 801 long save; 802 803 bcount = on; 804 bp = nfs_getcacheblk(vp, lbn, bcount, p); 805 save = bp->b_flags & B_CACHE; 806 |
790 np->n_size = uio->uio_offset + n; 791 np->n_flag |= NMODIFIED; 792 vnode_pager_setsize(vp, np->n_size); | 807 np->n_size = uio->uio_offset + n; 808 np->n_flag |= NMODIFIED; 809 vnode_pager_setsize(vp, np->n_size); |
810 811 bcount += n; 812 allocbuf(bp, bcount); 813 bp->b_flags |= save; 814 } else { 815 if (uio->uio_offset + n > np->n_size) { 816 np->n_size = uio->uio_offset + n; 817 np->n_flag |= NMODIFIED; 818 vnode_pager_setsize(vp, np->n_size); 819 } 820 bcount = biosize; 821 if ((off_t)(lbn + 1) * biosize > np->n_size) 822 bcount = np->n_size - (off_t)lbn * biosize; 823 bp = nfs_getcacheblk(vp, lbn, bcount, p); |
|
793 } | 824 } |
794 bufsize = biosize; 795 if ((off_t)(lbn + 1) * biosize > np->n_size) { 796 bufsize = np->n_size - (off_t)lbn * biosize; 797 bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); | 825 826 /* 827 * Issue a READ if B_CACHE is not set. In special-append 828 * mode, B_CACHE is based on the buffer prior to the write 829 * op and is typically set, avoiding the read. If a read 830 * is required in special append mode, the server will 831 * probably send us a short-read since we extended the file 832 * on our end, resulting in b_resid == 0 and, thusly, 833 * B_CACHE getting set. 834 * 835 * We can also avoid issuing the read if the write covers 836 * the entire buffer. We have to make sure the buffer state 837 * is reasonable in this case since we will not be initiating 838 * I/O. See the comments in kern/vfs_bio.c's getblk() for 839 * more information. 840 * 841 * B_CACHE may also be set due to the buffer being cached 842 * normally. 843 */ 844 845 if (on == 0 && n == bcount) { 846 bp->b_flags |= B_CACHE; 847 bp->b_flags &= ~(B_ERROR | B_INVAL); |
798 } | 848 } |
799 bp = nfs_getcacheblk(vp, lbn, bufsize, p); | 849 850 if ((bp->b_flags & B_CACHE) == 0) { 851 bp->b_flags |= B_READ; 852 vfs_busy_pages(bp, 0); 853 error = nfs_doio(bp, cred, p); 854 if (error) { 855 brelse(bp); 856 return (error); 857 } 858 } |
800 if (!bp) 801 return (EINTR); 802 if (bp->b_wcred == NOCRED) { 803 crhold(cred); 804 bp->b_wcred = cred; 805 } 806 np->n_flag |= NMODIFIED; 807 --- 7 unchanged lines hidden (view full) --- 815 bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE; 816 if (bp->b_dirtyoff >= bp->b_dirtyend) 817 bp->b_dirtyoff = bp->b_dirtyend = 0; 818 819 /* 820 * If the new write will leave a contiguous dirty 821 * area, just update the b_dirtyoff and b_dirtyend, 822 * otherwise force a write rpc of the old dirty area. | 859 if (!bp) 860 return (EINTR); 861 if (bp->b_wcred == NOCRED) { 862 crhold(cred); 863 bp->b_wcred = cred; 864 } 865 np->n_flag |= NMODIFIED; 866 --- 7 unchanged lines hidden (view full) --- 874 bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE; 875 if (bp->b_dirtyoff >= bp->b_dirtyend) 876 bp->b_dirtyoff = bp->b_dirtyend = 0; 877 878 /* 879 * If the new write will leave a contiguous dirty 880 * area, just update the b_dirtyoff and b_dirtyend, 881 * otherwise force a write rpc of the old dirty area. |
882 * 883 * While it is possible to merge discontiguous writes due to 884 * our having a B_CACHE buffer ( and thus valid read data 885 * for the hole), we don't because it could lead to 886 * significant cache coherency problems with multiple clients, 887 * especially if locking is implemented later on. 888 * 889 * as an optimization we could theoretically maintain 890 * a linked list of discontinuous areas, but we would still 891 * have to commit them separately so there isn't much 892 * advantage to it except perhaps a bit of asynchronization. |
|
823 */ 824 825 if (bp->b_dirtyend > 0 && 826 (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) { 827 bp->b_proc = p; 828 if (VOP_BWRITE(bp) == EINTR) 829 return (EINTR); 830 goto again; --- 27 unchanged lines hidden (view full) --- 858 bp->b_flags &= ~B_NEEDCOMMIT; 859 if (error) { 860 bp->b_flags |= B_ERROR; 861 brelse(bp); 862 return (error); 863 } 864 865 /* | 893 */ 894 895 if (bp->b_dirtyend > 0 && 896 (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) { 897 bp->b_proc = p; 898 if (VOP_BWRITE(bp) == EINTR) 899 return (EINTR); 900 goto again; --- 27 unchanged lines hidden (view full) --- 928 bp->b_flags &= ~B_NEEDCOMMIT; 929 if (error) { 930 bp->b_flags |= B_ERROR; 931 brelse(bp); 932 return (error); 933 } 934 935 /* |
866 * This will keep the buffer and mmaped regions more coherent. 867 */ 868 nfs_prot_buf(bp, on, n); 869 870 /* | |
871 * Only update dirtyoff/dirtyend if not a degenerate 872 * condition. 873 */ 874 if (n) { 875 if (bp->b_dirtyend > 0) { 876 bp->b_dirtyoff = min(on, bp->b_dirtyoff); 877 bp->b_dirtyend = max((on + n), bp->b_dirtyend); 878 } else { 879 bp->b_dirtyoff = on; 880 bp->b_dirtyend = on + n; 881 } | 936 * Only update dirtyoff/dirtyend if not a degenerate 937 * condition. 938 */ 939 if (n) { 940 if (bp->b_dirtyend > 0) { 941 bp->b_dirtyoff = min(on, bp->b_dirtyoff); 942 bp->b_dirtyend = max((on + n), bp->b_dirtyend); 943 } else { 944 bp->b_dirtyoff = on; 945 bp->b_dirtyend = on + n; 946 } |
947 vfs_bio_set_validclean(bp, on, n); |
|
882 } 883 884 /* | 948 } 949 950 /* |
885 * To avoid code complexity, we may have to throw away 886 * previously valid ranges when merging the new dirty range 887 * into the valid range. As long as we do not *ADD* an 888 * invalid valid range, we are ok. 889 */ 890 if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff || 891 bp->b_validoff > bp->b_dirtyend) { 892 bp->b_validoff = bp->b_dirtyoff; 893 bp->b_validend = bp->b_dirtyend; 894 } else { 895 bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff); 896 bp->b_validend = max(bp->b_validend, bp->b_dirtyend); 897 } 898 899 /* | |
900 * Since this block is being modified, it must be written 901 * again and not just committed. 902 */ 903 bp->b_flags &= ~B_NEEDCOMMIT; 904 905 /* 906 * If the lease is non-cachable or IO_SYNC do bwrite(). | 951 * Since this block is being modified, it must be written 952 * again and not just committed. 953 */ 954 bp->b_flags &= ~B_NEEDCOMMIT; 955 956 /* 957 * If the lease is non-cachable or IO_SYNC do bwrite(). |
958 * 959 * IO_INVAL appears to be unused. The idea appears to be 960 * to turn off caching in this case. Very odd. XXX |
|
907 */ 908 if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) { 909 bp->b_proc = p; 910 if (ioflag & IO_INVAL) | 961 */ 962 if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) { 963 bp->b_proc = p; 964 if (ioflag & IO_INVAL) |
911 bp->b_flags |= B_INVAL; | 965 bp->b_flags |= B_NOCACHE; |
912 error = VOP_BWRITE(bp); 913 if (error) 914 return (error); 915 if (np->n_flag & NQNFSNONCACHE) { 916 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); 917 if (error) 918 return (error); 919 } 920 } else if ((n + on) == biosize && 921 (nmp->nm_flag & NFSMNT_NQNFS) == 0) { 922 bp->b_proc = (struct proc *)0; 923 bp->b_flags |= B_ASYNC; 924 (void)nfs_writebp(bp, 0); | 966 error = VOP_BWRITE(bp); 967 if (error) 968 return (error); 969 if (np->n_flag & NQNFSNONCACHE) { 970 error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); 971 if (error) 972 return (error); 973 } 974 } else if ((n + on) == biosize && 975 (nmp->nm_flag & NFSMNT_NQNFS) == 0) { 976 bp->b_proc = (struct proc *)0; 977 bp->b_flags |= B_ASYNC; 978 (void)nfs_writebp(bp, 0); |
925 } else | 979 } else { |
926 bdwrite(bp); | 980 bdwrite(bp); |
981 } |
|
927 } while (uio->uio_resid > 0 && n > 0); 928 return (0); 929} 930 931/* 932 * Get an nfs cache block. 933 * Allocate a new one if the block isn't currently in the cache 934 * and return the block marked busy. If the calling process is --- 16 unchanged lines hidden (view full) --- 951 952 if (nmp->nm_flag & NFSMNT_INT) { 953 bp = getblk(vp, bn, size, PCATCH, 0); 954 while (bp == (struct buf *)0) { 955 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 956 return ((struct buf *)0); 957 bp = getblk(vp, bn, size, 0, 2 * hz); 958 } | 982 } while (uio->uio_resid > 0 && n > 0); 983 return (0); 984} 985 986/* 987 * Get an nfs cache block. 988 * Allocate a new one if the block isn't currently in the cache 989 * and return the block marked busy. If the calling process is --- 16 unchanged lines hidden (view full) --- 1006 1007 if (nmp->nm_flag & NFSMNT_INT) { 1008 bp = getblk(vp, bn, size, PCATCH, 0); 1009 while (bp == (struct buf *)0) { 1010 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 1011 return ((struct buf *)0); 1012 bp = getblk(vp, bn, size, 0, 2 * hz); 1013 } |
959 } else | 1014 } else { |
960 bp = getblk(vp, bn, size, 0, 0); | 1015 bp = getblk(vp, bn, size, 0, 0); |
1016 } |
|
961 962 if (vp->v_type == VREG) { 963 int biosize; | 1017 1018 if (vp->v_type == VREG) { 1019 int biosize; |
1020 |
|
964 biosize = mp->mnt_stat.f_iosize; 965 bp->b_blkno = bn * (biosize / DEV_BSIZE); 966 } | 1021 biosize = mp->mnt_stat.f_iosize; 1022 bp->b_blkno = bn * (biosize / DEV_BSIZE); 1023 } |
967 | |
968 return (bp); 969} 970 971/* 972 * Flush and invalidate all dirty buffers. If another process is already 973 * doing the flush, just wait for completion. 974 */ 975int --- 55 unchanged lines hidden (view full) --- 1031 } 1032 return (0); 1033} 1034 1035/* 1036 * Initiate asynchronous I/O. Return an error if no nfsiods are available. 1037 * This is mainly to avoid queueing async I/O requests when the nfsiods 1038 * are all hung on a dead server. | 1024 return (bp); 1025} 1026 1027/* 1028 * Flush and invalidate all dirty buffers. If another process is already 1029 * doing the flush, just wait for completion. 1030 */ 1031int --- 55 unchanged lines hidden (view full) --- 1087 } 1088 return (0); 1089} 1090 1091/* 1092 * Initiate asynchronous I/O. Return an error if no nfsiods are available. 1093 * This is mainly to avoid queueing async I/O requests when the nfsiods 1094 * are all hung on a dead server. |
1095 * 1096 * Note: nfs_asyncio() does not clear (B_ERROR|B_INVAL) but when the bp 1097 * is eventually dequeued by the async daemon, nfs_doio() *will*. |
|
1039 */ 1040int 1041nfs_asyncio(bp, cred) 1042 register struct buf *bp; 1043 struct ucred *cred; 1044{ 1045 struct nfsmount *nmp; 1046 int i; --- 112 unchanged lines hidden (view full) --- 1159 struct buf *bp; 1160 struct ucred *cr; 1161 struct proc *p; 1162{ 1163 struct uio *uiop; 1164 struct vnode *vp; 1165 struct nfsnode *np; 1166 struct nfsmount *nmp; | 1098 */ 1099int 1100nfs_asyncio(bp, cred) 1101 register struct buf *bp; 1102 struct ucred *cred; 1103{ 1104 struct nfsmount *nmp; 1105 int i; --- 112 unchanged lines hidden (view full) --- 1218 struct buf *bp; 1219 struct ucred *cr; 1220 struct proc *p; 1221{ 1222 struct uio *uiop; 1223 struct vnode *vp; 1224 struct nfsnode *np; 1225 struct nfsmount *nmp; |
1167 int error = 0, diff, len, iomode, must_commit = 0; | 1226 int error = 0, iomode, must_commit = 0; |
1168 struct uio uio; 1169 struct iovec io; 1170 1171 vp = bp->b_vp; 1172 np = VTONFS(vp); 1173 nmp = VFSTONFS(vp->v_mount); 1174 uiop = &uio; 1175 uiop->uio_iov = &io; 1176 uiop->uio_iovcnt = 1; 1177 uiop->uio_segflg = UIO_SYSSPACE; 1178 uiop->uio_procp = p; 1179 | 1227 struct uio uio; 1228 struct iovec io; 1229 1230 vp = bp->b_vp; 1231 np = VTONFS(vp); 1232 nmp = VFSTONFS(vp->v_mount); 1233 uiop = &uio; 1234 uiop->uio_iov = &io; 1235 uiop->uio_iovcnt = 1; 1236 uiop->uio_segflg = UIO_SYSSPACE; 1237 uiop->uio_procp = p; 1238 |
1239 /* 1240 * clear B_ERROR and B_INVAL state prior to initiating the I/O. We 1241 * do this here so we do not have to do it in all the code that 1242 * calls us. 1243 */ 1244 bp->b_flags &= ~(B_ERROR | B_INVAL); 1245 |
|
1180 KASSERT(!(bp->b_flags & B_DONE), ("nfs_doio: bp %p already marked done", bp)); 1181 1182 /* 1183 * Historically, paging was done with physio, but no more. 1184 */ 1185 if (bp->b_flags & B_PHYS) { 1186 /* 1187 * ...though reading /dev/drum still gets us here. --- 23 unchanged lines hidden (view full) --- 1211 io.iov_base = bp->b_data; 1212 uiop->uio_rw = UIO_READ; 1213 switch (vp->v_type) { 1214 case VREG: 1215 uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE; 1216 nfsstats.read_bios++; 1217 error = nfs_readrpc(vp, uiop, cr); 1218 if (!error) { | 1246 KASSERT(!(bp->b_flags & B_DONE), ("nfs_doio: bp %p already marked done", bp)); 1247 1248 /* 1249 * Historically, paging was done with physio, but no more. 1250 */ 1251 if (bp->b_flags & B_PHYS) { 1252 /* 1253 * ...though reading /dev/drum still gets us here. --- 23 unchanged lines hidden (view full) --- 1277 io.iov_base = bp->b_data; 1278 uiop->uio_rw = UIO_READ; 1279 switch (vp->v_type) { 1280 case VREG: 1281 uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE; 1282 nfsstats.read_bios++; 1283 error = nfs_readrpc(vp, uiop, cr); 1284 if (!error) { |
1219 bp->b_validoff = 0; | |
1220 if (uiop->uio_resid) { 1221 /* | 1285 if (uiop->uio_resid) { 1286 /* |
1222 * If len > 0, there is a hole in the file and 1223 * no writes after the hole have been pushed to 1224 * the server yet. 1225 * Just zero fill the rest of the valid area. | 1287 * If we had a short read with no error, we must have 1288 * hit a file hole. We should zero-fill the remainder. 1289 * This can also occur if the server hits the file EOF. 1290 * 1291 * Holes used to be able to occur due to pending 1292 * writes, but that is not possible any longer. |
1226 */ | 1293 */ |
1227 diff = bp->b_bcount - uiop->uio_resid; 1228 len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE 1229 + diff); 1230 if (len > 0) { 1231 len = min(len, uiop->uio_resid); 1232 bzero((char *)bp->b_data + diff, len); 1233 bp->b_validend = diff + len; 1234 } else 1235 bp->b_validend = diff; 1236 } else 1237 bp->b_validend = bp->b_bcount; | 1294 int nread = bp->b_bcount - uiop->uio_resid; 1295 int left = bp->b_bcount - nread; 1296 1297 if (left > 0) 1298 bzero((char *)bp->b_data + nread, left); 1299 uiop->uio_resid = 0; 1300 } |
1238 } 1239 if (p && (vp->v_flag & VTEXT) && 1240 (((nmp->nm_flag & NFSMNT_NQNFS) && 1241 NQNFS_CKINVALID(vp, np, ND_READ) && 1242 np->n_lrev != np->n_brev) || 1243 (!(nmp->nm_flag & NFSMNT_NQNFS) && 1244 np->n_mtime != np->n_vattr.va_mtime.tv_sec))) { 1245 uprintf("Process killed due to text file modification\n"); --- 11 unchanged lines hidden (view full) --- 1257 uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ; 1258 if (nmp->nm_flag & NFSMNT_RDIRPLUS) { 1259 error = nfs_readdirplusrpc(vp, uiop, cr); 1260 if (error == NFSERR_NOTSUPP) 1261 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 1262 } 1263 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) 1264 error = nfs_readdirrpc(vp, uiop, cr); | 1301 } 1302 if (p && (vp->v_flag & VTEXT) && 1303 (((nmp->nm_flag & NFSMNT_NQNFS) && 1304 NQNFS_CKINVALID(vp, np, ND_READ) && 1305 np->n_lrev != np->n_brev) || 1306 (!(nmp->nm_flag & NFSMNT_NQNFS) && 1307 np->n_mtime != np->n_vattr.va_mtime.tv_sec))) { 1308 uprintf("Process killed due to text file modification\n"); --- 11 unchanged lines hidden (view full) --- 1320 uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ; 1321 if (nmp->nm_flag & NFSMNT_RDIRPLUS) { 1322 error = nfs_readdirplusrpc(vp, uiop, cr); 1323 if (error == NFSERR_NOTSUPP) 1324 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 1325 } 1326 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) 1327 error = nfs_readdirrpc(vp, uiop, cr); |
1328 /* 1329 * end-of-directory sets B_INVAL but does not generate an 1330 * error. 1331 */ |
|
1265 if (error == 0 && uiop->uio_resid == bp->b_bcount) 1266 bp->b_flags |= B_INVAL; 1267 break; 1268 default: 1269 printf("nfs_doio: type %x unexpected\n",vp->v_type); 1270 break; 1271 }; 1272 if (error) { --- 18 unchanged lines hidden (view full) --- 1291 else 1292 iomode = NFSV3WRITE_FILESYNC; 1293 1294 bp->b_flags |= B_WRITEINPROG; 1295 error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit); 1296 if (!error && iomode == NFSV3WRITE_UNSTABLE) { 1297 bp->b_flags |= B_NEEDCOMMIT; 1298 if (bp->b_dirtyoff == 0 | 1332 if (error == 0 && uiop->uio_resid == bp->b_bcount) 1333 bp->b_flags |= B_INVAL; 1334 break; 1335 default: 1336 printf("nfs_doio: type %x unexpected\n",vp->v_type); 1337 break; 1338 }; 1339 if (error) { --- 18 unchanged lines hidden (view full) --- 1358 else 1359 iomode = NFSV3WRITE_FILESYNC; 1360 1361 bp->b_flags |= B_WRITEINPROG; 1362 error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit); 1363 if (!error && iomode == NFSV3WRITE_UNSTABLE) { 1364 bp->b_flags |= B_NEEDCOMMIT; 1365 if (bp->b_dirtyoff == 0 |
1299 && bp->b_dirtyend == bp->b_bufsize) | 1366 && bp->b_dirtyend == bp->b_bcount) |
1300 bp->b_flags |= B_CLUSTEROK; 1301 } else { 1302 bp->b_flags &= ~B_NEEDCOMMIT; 1303 } 1304 bp->b_flags &= ~B_WRITEINPROG; 1305 1306 /* 1307 * For an interrupted write, the buffer is still valid --- 49 unchanged lines hidden --- | 1367 bp->b_flags |= B_CLUSTEROK; 1368 } else { 1369 bp->b_flags &= ~B_NEEDCOMMIT; 1370 } 1371 bp->b_flags &= ~B_WRITEINPROG; 1372 1373 /* 1374 * For an interrupted write, the buffer is still valid --- 49 unchanged lines hidden --- |