Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_inode.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_inode.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.13 retrieving revision 1.13.4.4 diff -u -p -r1.13 -r1.13.4.4 --- src/sys/ufs/ufs/ufs_inode.c 1999/03/05 21:09:50 1.13 +++ src/sys/ufs/ufs/ufs_inode.c 1999/08/06 12:50:27 1.13.4.4 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_inode.c,v 1.13 1999/03/05 21:09:50 mycroft Exp $ */ +/* $NetBSD: ufs_inode.c,v 1.13.4.4 1999/08/06 12:50:27 chs Exp $ */ /* * Copyright (c) 1991, 1993 @@ -55,6 +55,8 @@ #include #include +#include + /* * Last reference to an inode. If necessary, write or delete it. */ @@ -146,3 +148,112 @@ ufs_reclaim(vp, p) #endif return (0); } + +/* + * allocate a range of blocks in a file. + * after this function returns, any page entirely contained within the range + * will map to invalid data and thus must be overwritten before it is made + * accessible to others. + */ + +int +ufs_balloc_range(vp, off, len, cred, flags) + struct vnode *vp; + off_t off, len; + struct ucred *cred; + int flags; +{ + off_t eof, pagestart, pageend; + struct uvm_object *uobj; + struct inode *ip = VTOI(vp); + int i, delta, error, npages1, npages2; + int bshift = vp->v_mount->mnt_fs_bshift; + int bsize = 1 << bshift; + int ppb = max(bsize >> PAGE_SHIFT, 1); + struct vm_page *pgs1[ppb], *pgs2[ppb]; + UVMHIST_FUNC("ufs_balloc_range"); UVMHIST_CALLED(ubchist); + UVMHIST_LOG(ubchist, "vp %p off 0x%x len 0x%x u_size 0x%x", + vp, (int)off, (int)len, (int)vp->v_uvm.u_size); + + /* + * if the range does not start on a page and block boundary, + * cache the first block if the file so the page(s) will contain + * the correct data. hold the page(s) busy while we allocate + * the backing store for the range. + */ + + uobj = &vp->v_uvm.u_obj; + eof = max(vp->v_uvm.u_size, off + len); + vp->v_uvm.u_size = eof; + UVMHIST_LOG(ubchist, "new eof 0x%x", (int)eof,0,0,0); + error = 0; + pgs1[0] = pgs2[0] = NULL; + pagestart = trunc_page(off) & ~(bsize - 1); + if (off != pagestart) { + npages1 = min(ppb, (round_page(eof) - pagestart) >> + PAGE_SHIFT); + memset(pgs1, 0, npages1); + simple_lock(&uobj->vmobjlock); + error = VOP_GETPAGES(vp, pagestart, pgs1, &npages1, 0, + VM_PROT_READ, 0, PGO_SYNCIO); + if (error) { + goto errout; + } + for (i = 0; i < npages1; i++) { + UVMHIST_LOG(ubchist, "got pgs1[%d] %p", i, pgs1[i],0,0); + } + } + + /* + * similarly if the range does not end on a page and block boundary. + */ + + pageend = trunc_page(off + len) & ~(bsize - 1); + if (off + len < ip->i_ffs_size && + off + len != pageend && + pagestart != pageend) { + npages2 = min(ppb, (round_page(eof) - pageend) >> + PAGE_SHIFT); + memset(pgs2, 0, npages2); + simple_lock(&uobj->vmobjlock); + error = VOP_GETPAGES(vp, pageend, pgs2, &npages2, 0, + VM_PROT_READ, 0, PGO_SYNCIO); + if (error) { + goto errout; + } + for (i = 0; i < npages2; i++) { + UVMHIST_LOG(ubchist, "got pgs2[%d] %p", i, pgs2[i],0,0); + } + } + + /* + * adjust off to be block-aligned. + */ + + delta = off & (bsize - 1); + off -= delta; + len += delta; + + /* + * now allocate the range. + */ + + if ((error = VOP_BALLOC(vp, off, len, cred, flags))) { + goto errout; + } + + /* + * unbusy any pages we are holding. + */ + +errout: + simple_lock(&uobj->vmobjlock); + if (pgs1[0] != NULL) { + uvm_page_unbusy(pgs1, npages1); + } + if (pgs2[0] != NULL) { + uvm_page_unbusy(pgs2, npages2); + } + simple_unlock(&uobj->vmobjlock); + return error; +}