⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freebsd-3.2.il-kernel.patch

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+ 		/*+ 		 * Start the read ahead(s), as required.+ 		 */+ 		if (u9fs_numasync > 0 && nmp->nm_readahead > 0) {+ 		    for (nra = 0; nra < nmp->nm_readahead &&+ 			(off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) {+ 			rabn = lbn + 1 + nra;+ 			if (!incore(vp, rabn)) {+ 			    rabp = u9fs_getcacheblk(vp, rabn, biosize, p);+ 			    if (!rabp)+ 				return (EINTR);+ 			    if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {+ 				rabp->b_flags |= (B_READ | B_ASYNC);+ 				vfs_busy_pages(rabp, 0);+ 				if (u9fs_asyncio(rabp, cred)) {+ 				    rabp->b_flags |= B_INVAL|B_ERROR;+ 				    vfs_unbusy_pages(rabp);+ 				    brelse(rabp);+ 				}+ 			    } else+ 				brelse(rabp);+ 			}+ 		    }+ 		}+ #endif+ + 		/*+ 		 * If the block is in the cache and has the required data+ 		 * in a valid region, just copy it out.+ 		 * Otherwise, get the block and write back/read in,+ 		 * as required.+ 		 */+ again:+ 		bufsize = biosize;+ 		if ((off_t)(lbn + 1) * biosize > np->n_size && + 		    (off_t)(lbn + 1) * biosize - np->n_size < biosize) {+ 			bufsize = np->n_size - (off_t)lbn * biosize;+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);+ 		}+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);+ 		if (!bp)+ 			return (EINTR);+ 		/*+ 		 * If we are being called from u9fs_getpages, we must+ 		 * make sure the buffer is a vmio buffer.  The vp will+ 		 * already be setup for vmio but there may be some old+ 		 * non-vmio buffers attached to it.+ 		 */+ 		if (getpages && !(bp->b_flags & B_VMIO)) {+ #ifdef DIAGNOSTIC+ 			printf("u9fs_bioread: non vmio buf found, discarding\n");+ #endif+ 			bp->b_flags |= B_NOCACHE;+ 			if (bp->b_dirtyend > 0) {+ 				if ((bp->b_flags & B_DELWRI) == 0)+ 					panic("u9fsbioread");+ 				if (VOP_BWRITE(bp) == EINTR)+ 					return (EINTR);+ 			} else+ 				brelse(bp);+ 			goto again;+ 		}+ 		if ((bp->b_flags & B_CACHE) == 0) {+ 		    bp->b_flags |= B_READ;+ 		    bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL);+ 		    not_readin = 0;+ 		    vfs_busy_pages(bp, 0);+ 		    error = u9fs_doio(bp, cred, p);+ 		    if (error) {+ 			brelse(bp);+ 			return (error);+ 		    }+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;+ 		}+ 		if (bufsize > on) {+ 			n = min((unsigned)(bufsize - on), uio->uio_resid);+ 		} else {+ 			n = 0;+ 		}+ 		diff = np->n_size - uio->uio_offset;+ 		if (diff < n)+ 			n = diff;+ 		if (not_readin && n > 0) {+ 			if (on < bp->b_validoff || (on + n) > bp->b_validend) {+ 				bp->b_flags |= B_NOCACHE;+ 				if (bp->b_dirtyend > 0) {+ 				    if ((bp->b_flags & B_DELWRI) == 0)+ 					panic("u9fsbioread");+ 				    if (VOP_BWRITE(bp) == EINTR)+ 					return (EINTR);+ 				} else+ 				    brelse(bp);+ 				goto again;+ 			}+ 		}+ 		vp->v_lastr = lbn;+ 		diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on);+ 		if (diff < n)+ 			n = diff;+ 		break;+ 	    case VDIR:+ 	        biosize = nmp->nm_readdirsize;+ 		lbn = (uoff_t)uio->uio_offset / biosize;+ 		on = uio->uio_offset % biosize;+ 		bp = u9fs_getcacheblk(vp, lbn, biosize, p);+ 		if (!bp)+ 		    return (EINTR);+ 		if ((bp->b_flags & B_CACHE) == 0) {+ 		    bp->b_flags |= B_READ;+ 		    vfs_busy_pages(bp, 0);+ 		    error = u9fs_doio(bp, cred, p);+ 		    if (error) {+ 			    brelse(bp);+ 		    }+ 		    if (error)+ 			    return (error);+ 		    np->n_qid.vers = np->n_dir.dir_qid.vers;+ 		}+ + 		/*+ 		 * Make sure we use a signed variant of min() since+ 		 * the second term may be negative.+ 		 */+ 		n = lmin(uio->uio_resid, biosize - bp->b_resid - on);+ 		break;+ 	    default:+ 		printf(" u9fs_bioread: type %x unexpected\n",vp->v_type);+ 		break;+ 	    };+ + 	    if (n > 0) {+ 		    error = uiomove(bp->b_data + on, (int)n, uio);+ 	    }+ 	    brelse(bp);+ 	} while (error == 0 && uio->uio_resid > 0 && n > 0);+ 	return (error);+ }+ + /*+  * Vnode op for write using bio+  */+ int+ u9fs_biowrite(vp, uio, ioflag, cred)+      register struct vnode *vp;+      register struct uio *uio;+      register int  ioflag;+      register struct ucred *cred;+ {+   register int biosize;+   struct proc *p = uio->uio_procp;+   struct u9fsnode *np = VTOU9FS(vp);+   struct buf *bp;+   struct vattr vattr;+   struct u9fsmount *nmp = VFSTOU9FS(vp->v_mount);+   daddr_t lbn;+   int bufsize;+   int n, on, error = 0;+ +   if (ioflag & (IO_APPEND | IO_SYNC)) {+     if (ioflag & IO_APPEND) {+       error = VOP_GETATTR(vp, &vattr, cred, p);+       if (error)+ 	return (error);+       uio->uio_offset = np->n_size;+     }+   }+   if (uio->uio_offset < 0)+     return (EINVAL);+   if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)+     return (EFBIG);+   if (uio->uio_resid == 0)+     return (0);+ + 	/*+ 	 * I use nm_rsize, not nm_wsize so that all buffer cache blocks+ 	 * will be the same size within a filesystem. nfs_writerpc will+ 	 * still use nm_wsize when sizing the rpc's.+ 	 */+ 	biosize = vp->v_mount->mnt_stat.f_iosize;+ 	do {+ 		lbn = uio->uio_offset / biosize;+ 		on = uio->uio_offset & (biosize-1);+ 		n = min((unsigned)(biosize - on), uio->uio_resid);+ 		if (uio->uio_offset + n > np->n_size) {+ 			np->n_size = uio->uio_offset + n;+ 			vnode_pager_setsize(vp, np->n_size);+ 		}+ 		bufsize = biosize;+ 		if ((off_t)(lbn + 1) * biosize > np->n_size) {+ 			bufsize = np->n_size - (off_t)lbn * biosize;+ 			bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);+ 		}+ 		bp = u9fs_getcacheblk(vp, lbn, bufsize, p);+ 		if (!bp)+ 			return (EINTR);+ 		if (bp->b_wcred == NOCRED) {+ 			crhold(cred);+ 			bp->b_wcred = cred;+ 		}+ + 		error = uiomove((char *)bp->b_data + on, n, uio);+ 		if (error) {+ 			bp->b_flags |= B_ERROR;+ 			brelse(bp);+ 			return (error);+ 		}+ + 		/*+ 		 * This will keep the buffer and mmaped regions more coherent.+ 		 */+ 		u9fs_prot_buf(bp, on, n);+ 		bp->b_dirtyoff = on;+ 		bp->b_dirtyend = on + n;+ + 		if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||+ 		    bp->b_validoff > bp->b_dirtyend) {+ 		  /* XXX: destroys our read cache if not overlapping */+ 		  /* two choice: none implemented+ 		     1> keep the bigger(smaller) piece+ 		     2> read the missing segment		     + 		  */+ 			bp->b_validoff = bp->b_dirtyoff;+ 			bp->b_validend = bp->b_dirtyend;+ 		} else {+ 			bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);+ 			bp->b_validend = max(bp->b_validend, bp->b_dirtyend);+ 		}+ + 		error = bwrite(bp);+ 		if( error ) {+ 		  bp->b_flags |= B_ERROR;+ 		  /* brelse(bp); */+ 		  return error;		  + 		}+ 	} while (uio->uio_resid > 0 && n > 0);+ 	return 0;+ }+ + /*+  * Do an I/O operation to/from a cache block. This may be called+  * synchronously or from an u9fsiod.+  */+ int+ u9fs_doio(bp, cr, p)+ 	register struct buf *bp;+ 	struct ucred *cr;+ 	struct proc *p;+ {+ 	register struct uio *uiop;+ 	register struct vnode *vp;+ 	struct u9fsnode *np;+ 	struct u9fsmount *nmp;+ 	int error = 0, diff, len;+ 	struct uio uio;+ 	struct iovec io;+ + 	vp = bp->b_vp;+ 	np = VTOU9FS(vp);+ 	nmp = VFSTOU9FS(vp->v_mount);+ 	uiop = &uio;+ 	uiop->uio_iov = &io;+ 	uiop->uio_iovcnt = 1;+ 	uiop->uio_segflg = UIO_SYSSPACE;+ 	uiop->uio_procp = p;+ + 	if (bp->b_flags & B_READ ) {+ 	    io.iov_len = uiop->uio_resid = bp->b_bcount;+ 	    io.iov_base = bp->b_data;+ 	    uiop->uio_rw = UIO_READ;+ 	    switch (vp->v_type) {+ 	    case VREG:+ 		uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;+ 		error = u9fs_readrpc(vp, uiop, cr);+ 		if (!error) {+ 		    bp->b_validoff = 0;+ 		    if (uiop->uio_resid) {+ 			/*+ 			 * If len > 0, there is a hole in the file and+ 			 * no writes after the hole have been pushed to+ 			 * the server yet.+ 			 * Just zero fill the rest of the valid area.+ 			 */+ 			diff = bp->b_bcount - uiop->uio_resid;+ 			len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE+ 				+ diff);+ 			if (len > 0) {+ 			    len = min(len, uiop->uio_resid);+ 			    bzero((char *)bp->b_data + diff, len);+ 			    bp->b_validend = diff + len;+ 			} else+ 			    bp->b_validend = diff;+ 		    } else+ 			bp->b_validend = bp->b_bcount;+ 		}+ 		break;+ 	    case VDIR:+ 		uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * nmp->nm_readdirsize;+ 		error = u9fs_readdirrpc(vp, uiop, cr);+ 		if (error == 0 && uiop->uio_resid == bp->b_bcount)+ 		  bp->b_flags |= B_INVAL;+ 		break;+ 	    default:+ 		printf("u9fs_doio:  type %x unexpected\n",vp->v_type);+ 		break;+ 	    };+ 	    if (error) {+ 		bp->b_flags |= B_ERROR;+ 		bp->b_error = error;+ 	    }+ 	} else {+ 	    if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)+ 		bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;+ + 	    if (bp->b_dirtyend > bp->b_dirtyoff) {+ 		io.iov_len = uiop->uio_resid = bp->b_dirtyend+ 		    - bp->b_dirtyoff;+ 		uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE+ 		    + bp->b_dirtyoff;+ 		io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;+ 		uiop->uio_rw = UIO_WRITE;+ 		bp->b_flags |= B_WRITEINPROG;+ 		error = u9fs_writerpc(vp, uiop, cr);+ 		bp->b_flags &= ~B_WRITEINPROG;+ + 		if (error) {+ 		  bp->b_flags |= B_ERROR;+ 		  bp->b_error = np->n_error = error;+ 		  np->n_flag |= NWRITEERR;+ 		}+ 		bp->b_dirtyoff = bp->b_dirtyend = 0;+ 	    } else {+ 		bp->b_resid = 0;+ 		biodone(bp);+ 		return (0);+ 	    }+ 	}+ 	bp->b_resid = uiop->uio_resid;+ 	biodone(bp);+ 	return error;+ }+ + /*+  * Get an u9fs cache block.+  * Allocate a new one if the block isn't currently in the cache+  * and return the block marked busy. If the calling process is+  * interrupted by a signal for an interruptible mount point, return+  * NULL.+  */+ static struct buf *+ u9fs_getcacheblk(vp, bn, size, p)+ 	struct vnode *vp;+ 	daddr_t bn;+ 	int size;+ 	struct proc *p;+ {+ 	register struct buf *bp;+ 	struct mount *mp;+ 	struct u9fsmount *nmp;+ + 	mp = vp->v_mount;+ 	nmp = VFSTOU9FS(mp);+ + 	if (nmp->nm_flag & U9FSMNT_INT) {+ 		bp = getblk(vp, bn, size, PCATCH, 0);+ 		while (bp == (struct buf *)0) {+ 			if (u9fs_sigintr(nmp, p))+ 				return ((struct buf *)0);+ 			bp = getblk(vp, bn, size, 0, 2 * hz);+ 		}+ 	} else+ 		bp = getblk(vp, bn, size, 0, 0);+ + 	if (vp->v_type == VREG) {+ 		int biosize;+ 		biosize = mp->mnt_stat.f_iosize;+ 		bp->b_blkno = bn * (biosize / DEV_BSIZE);+ 	}+ + 	return (bp);+ }+ + static void+ u9fs_prot_buf(bp, off, n)+ 	struct buf *bp;+ 	int off;+ 	int n;+ {+ 	int pindex, boff, end;+ + 	if ((bp->b_flags & B_VMIO) == 0)+ 		return;+ + 	end = round_page(off + n);+ 	for (boff = trunc_page(off); boff < end; boff += PAGE_SIZE) {+ 		pindex = boff >> PAGE_SHIFT;+ 		vm_page_protect(bp->b_pages[pindex], VM_PROT_NONE);+ 	}+ }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -