diff --git a/sys/fs/devfs/devfs_vnops.pas b/sys/fs/devfs/devfs_vnops.pas index 2f63913d..39b774d1 100644 --- a/sys/fs/devfs/devfs_vnops.pas +++ b/sys/fs/devfs/devfs_vnops.pas @@ -205,7 +205,8 @@ uses kern_proc, kern_descrip, kern_mtxpool, - subr_uio; + subr_uio, + vnode_pager; function VFSTODEVFS(mp:p_mount):p_devfs_mount; inline; begin @@ -1641,7 +1642,7 @@ begin end; mtx_unlock(devfs_de_interlock); - //vnode_destroy_vobject(vp); + vnode_destroy_vobject(vp); VI_LOCK(vp); dev_lock(); diff --git a/sys/fs/ufs/ufs_vnops.pas b/sys/fs/ufs/ufs_vnops.pas index 3b1a00bb..54b3f370 100644 --- a/sys/fs/ufs/ufs_vnops.pas +++ b/sys/fs/ufs/ufs_vnops.pas @@ -101,7 +101,8 @@ uses kern_thr, kern_proc, vfs_subr, - subr_uio; + subr_uio, + vnode_pager; const UFS_DEL_VNLOCKED =$01; @@ -1026,7 +1027,7 @@ begin ufs_relv(vp); - //vnode_destroy_vobject(vp); + vnode_destroy_vobject(vp); Exit(0); end; diff --git a/sys/kern/kern_budget.pas b/sys/kern/kern_budget.pas index b6805cba..a1b5e266 100644 --- a/sys/kern/kern_budget.pas +++ b/sys/kern/kern_budget.pas @@ -20,18 +20,18 @@ type //budget resid const - SCE_KERNEL_BUDGET_MEMORY_INVALID=0; - SCE_KERNEL_BUDGET_MEMORY_DMEM =1; - SCE_KERNEL_BUDGET_MEMORY_VMEM =2; - SCE_KERNEL_BUDGET_MEMORY_MLOCK =3; - SCE_KERNEL_BUDGET_CPU_SET =4; - SCE_KERNEL_BUDGET_FD_FILE =5; - SCE_KERNEL_BUDGET_FD_SOCKET =6; - SCE_KERNEL_BUDGET_FD_EQUEUE =7; - SCE_KERNEL_BUDGET_FD_PIPE =8; - SCE_KERNEL_BUDGET_FD_DEVICE =9; - SCE_KERNEL_BUDGET_THREADS =10; - SCE_KERNEL_BUDGET_FD_IPCSOCKET =11; + SCE_KERNEL_BUDGET_INVALID =0; + SCE_KERNEL_BUDGET_MEMORY_DMEM =1; + SCE_KERNEL_BUDGET_MEMORY_VMEM =2; + SCE_KERNEL_BUDGET_MEMORY_MLOCK=3; + SCE_KERNEL_BUDGET_CPU_SET =4; + SCE_KERNEL_BUDGET_FD_FILE =5; + SCE_KERNEL_BUDGET_FD_SOCKET =6; + SCE_KERNEL_BUDGET_FD_EQUEUE =7; + SCE_KERNEL_BUDGET_FD_PIPE =8; + SCE_KERNEL_BUDGET_FD_DEVICE =9; + SCE_KERNEL_BUDGET_THREADS =10; + SCE_KERNEL_BUDGET_FD_IPCSOCKET=11; //budget proc_type PTYPE_BIG_APP = 0; diff --git a/sys/kern/kern_rtld.pas b/sys/kern/kern_rtld.pas index 6095193f..d718bcf3 100644 --- a/sys/kern/kern_rtld.pas +++ b/sys/kern/kern_rtld.pas @@ -463,7 +463,7 @@ begin if (imgp=nil) then Exit; imgp^.authinfo:=Default(t_authinfo); - imgp^.authinfo.app_caps [0]:=QWORD($2000000000000000); //IsGameProcess1 + imgp^.authinfo.app_caps [0]:=QWORD($2000000000000000); //IsGame imgp^.authinfo.app_attrs[0]:=$400000 or $800000; //allow dmem map if (imgp^.image_header=nil) or diff --git a/sys/md/md_vnops.pas b/sys/md/md_vnops.pas index 10729c90..9bee3b75 100644 --- a/sys/md/md_vnops.pas +++ b/sys/md/md_vnops.pas @@ -123,7 +123,8 @@ uses vstat, vfs_subr, subr_uio, - kern_thr; + kern_thr, + vnode_pager; const UFS_SET_READONLY=(not &0222); @@ -1094,7 +1095,7 @@ begin md_delete_cache(de); end; - //vnode_destroy_vobject(vp); + vnode_destroy_vobject(vp); Exit(0); end; @@ -1944,7 +1945,7 @@ begin VLNK:Exit(0); VDIR:Exit(0); else - Exit(EPERM); + Exit(EOPNOTSUPP); end; de:=vp^.v_data; @@ -1997,6 +1998,8 @@ begin vp^.v_un:=Pointer(FD); + vnode_create_vobject(vp, de^.ufs_size); + if ((de^.ufs_flags and UFS_CREATE)<>0) then begin if ((flags and O_EXCL)<>0) then @@ -2028,6 +2031,8 @@ begin NtClose(FD); end; + vnode_destroy_vobject(vp); + Result:=0; end; @@ -2259,6 +2264,8 @@ begin if (Result<>0) then goto _err; de^.ufs_size:=SIZE; + + vnode_pager_setsize(vp, SIZE); end; _err: @@ -2396,6 +2403,19 @@ begin Dec(uio^.uio_iovcnt); end; + if (Result=0) and (uio^.uio_rw=UIO_WRITE) then + begin + if not locked then + begin + sx_xlock(@de^.ufs_md_lock); + end; + + md_update_dirent(F,de,nil); + + vnode_pager_setsize(vp, de^.ufs_size); + + sx_xunlock(@de^.ufs_md_lock); + end else if locked then begin sx_xunlock(@de^.ufs_md_lock); diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index cdc1de9d..0226130f 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -799,6 +799,10 @@ + + + + diff --git a/sys/vfs/vfs_subr.pas b/sys/vfs/vfs_subr.pas index 017214b0..53ef239c 100644 --- a/sys/vfs/vfs_subr.pas +++ b/sys/vfs/vfs_subr.pas @@ -2164,8 +2164,8 @@ var mp:p_mount; begin Inc(vp^.v_holdcnt); - if (not VSHOULDBUSY(vp)) then - Exit; + if (not VSHOULDBUSY(vp)) then Exit; + ASSERT_VI_LOCKED(vp,'vholdl'); Assert((vp^.v_iflag and VI_FREE)<>0,'vnode not free'); Assert(vp^.v_op<>nil,'vholdl: vnode already reclaimed.'); @@ -2659,7 +2659,7 @@ begin begin obj:=vp^.v_object; if (obj<>nil) and - {((obj^.flags and OBJ_MIGHTBEDIRTY)<>0)} False and + ((obj^.flags and OBJ_MIGHTBEDIRTY)<>0) and ((flags=MNT_WAIT) or (VOP_ISLOCKED(vp)=0)) then begin if (vget(vp, LK_EXCLUSIVE or LK_RETRY or LK_INTERLOCK)=0) then @@ -2960,17 +2960,21 @@ begin error:=0; dev_lock(); if (vp^.v_type<>VCHR) then + begin error:=ENOTBLK - else + end else if (vp^.v_rdev=nil) then + begin error:=ENXIO - else + end else if (p_cdev(vp^.v_rdev)^.si_devsw=nil) then begin error:=ENXIO - end{ else - if ((p_cdev(vp^.v_rdev)^.si_devsw^.d_flags and D_DISK)=0) then - error:=ENOTBLK}; + end else + if ((p_cdevsw(p_cdev(vp^.v_rdev)^.si_devsw)^.d_flags and D_DISK)=0) then + begin + error:=ENOTBLK; + end; dev_unlock(); error:=ENOTBLK; if (errp<>nil) then diff --git a/sys/vfs/vnode.pas b/sys/vfs/vnode.pas index 1f623f53..8241aae4 100644 --- a/sys/vfs/vnode.pas +++ b/sys/vfs/vnode.pas @@ -311,6 +311,8 @@ procedure vn_rangelock_unlock_range(vp:p_vnode;cookie:Pointer;start,__end:Int64) function vn_rangelock_rlock(vp:p_vnode;start,__end:Int64):Pointer; function vn_rangelock_wlock(vp:p_vnode;start,__end:Int64):Pointer; +function vn_canvmio(vp:p_vnode):Boolean; + var rootvnode:p_vnode=nil; @@ -463,5 +465,22 @@ begin //Result:=rangelock_wlock(@vp^.v_rl, start, __end, VI_MTX(vp)) end; +const + vmiodirenable=False; + +function vn_canvmio(vp:p_vnode):Boolean; +begin + if (vp<>nil) then + begin + if (vp^.v_type=VREG) or + (vmiodirenable and (vp^.v_type=VDIR)) then + begin + Exit(True); + end; + end; + Result:=False; +end; + + end. diff --git a/sys/vm/sys_vm_object.pas b/sys/vm/sys_vm_object.pas index cb4c9a09..11eed5c1 100644 --- a/sys/vm/sys_vm_object.pas +++ b/sys/vm/sys_vm_object.pas @@ -32,9 +32,7 @@ type vm_object_t=^t_vm_object; t_vm_object=packed record mtx :mtx; - memq :TAILQ_HEAD; // list of resident pages patchq :TAILQ_HEAD; // list of patches - root :Pointer; // root of the resident page splay tree size :vm_pindex_t; // Object size generation :Integer; // generation ID ref_count :Integer; // How many refs?? @@ -118,6 +116,15 @@ function vm_object_page_clean(obj:vm_object_t; implementation +uses + vnode; + +// + +procedure vref(vp:p_vnode); external; + +// + function VM_OBJECT_MTX(obj:vm_object_t):p_mtx; begin Result:=@obj^.mtx; @@ -166,7 +173,6 @@ begin mtx_init(Result^.mtx,'vm_object'); - TAILQ_INIT(@Result^.memq); TAILQ_INIT(@Result^.patchq); Result^.otype :=t; @@ -190,7 +196,19 @@ procedure vm_object_reference(obj:vm_object_t); begin if (obj=nil) then Exit; - System.InterlockedIncrement(obj^.ref_count); + VM_OBJECT_LOCK(obj); + + Inc(obj^.ref_count); + + if (obj^.otype=OBJT_VNODE) then + begin + if (obj^.otype=OBJT_VNODE) then + begin + vref(obj^.handle); + end; + end; + + VM_OBJECT_UNLOCK(obj); end; procedure vm_object_pip_add(obj:vm_object_t;i:word); diff --git a/sys/vm/vm_mmap.pas b/sys/vm/vm_mmap.pas index 86994033..24e043a7 100644 --- a/sys/vm/vm_mmap.pas +++ b/sys/vm/vm_mmap.pas @@ -181,7 +181,7 @@ begin end; foff:=foffp^; flags:=flagsp^; - obj:=nil; + obj:=vp^.v_object; case vp^.v_type of @@ -258,12 +258,14 @@ begin begin flags:=flags or MAP_NOSYNC; end; + obj:=vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff); if (obj=nil) then begin error:=ENOMEM; goto done; end; + objp^:=obj; flagsp^:=flags; @@ -276,7 +278,9 @@ done: writecounted^:=FALSE; //vnode_pager_update_writecount(obj, objsize, 0); end; + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); Result:=(error); end; diff --git a/sys/vm/vm_object.pas b/sys/vm/vm_object.pas index 090db639..0778146a 100644 --- a/sys/vm/vm_object.pas +++ b/sys/vm/vm_object.pas @@ -38,7 +38,11 @@ implementation uses vmparam, vnode, - vfs_subr; + vnode_if, + vmount, + vfs_subr, + vfs_vnops, + kern_mtx; // @@ -71,7 +75,7 @@ end; The object must be locked. This routine may block. } -procedure vm_object_terminate(obj:vm_object_t); +procedure vm_object_terminate(obj:vm_object_t); public; var vp:p_vnode; begin @@ -118,26 +122,112 @@ begin vm_object_destroy(obj); end; -procedure vm_object_deallocate(obj:vm_object_t); public; +{ + Handle deallocating an object of type OBJT_VNODE. +} +procedure vm_object_vndeallocate(obj:vm_object_t); var - ref:Integer; + vp:p_vnode; +begin + vp:=obj^.handle; + + VFS_ASSERT_GIANT(vp^.v_mount); + VM_OBJECT_LOCK_ASSERT(obj); + + Assert(obj^.otype=OBJT_VNODE,'vm_object_vndeallocate: not a vnode obj'); + Assert(vp<>nil, 'vm_object_vndeallocate: missing vp'); + + if (obj^.ref_count > 1) then + begin + VM_OBJECT_UNLOCK(obj); + // vrele may need the vnode lock. + vrele(vp); + end else + begin + vhold(vp); + VM_OBJECT_UNLOCK(obj); + + vn_lock(vp, LK_EXCLUSIVE or LK_RETRY); + vdrop(vp); + + VM_OBJECT_LOCK(obj); + + Dec(obj^.ref_count); + + if (obj^.otype=OBJT_DEAD) then + begin + VM_OBJECT_UNLOCK(obj); + VOP_UNLOCK(vp, 0); + end else + begin + if (obj^.ref_count=0) then + begin + //VOP_UNSET_TEXT(vp); + end; + VM_OBJECT_UNLOCK(obj); + vput(vp); + end; + end; +end; + +{ + vm_object_deallocate: + + Release a reference to the specified object, + gained either through a vm_object_allocate + or a vm_object_reference call. When all references + are gone, storage associated with this object + may be relinquished. + + No object may be locked. +} +procedure vm_object_deallocate(obj:vm_object_t); public; +label + restart; +var + vfslocked:Integer; + vp:p_vnode; begin if (obj=nil) then Exit; - ref:=System.InterlockedDecrement(obj^.ref_count); + VM_OBJECT_LOCK(obj); - if (ref=1) then - begin - VM_OBJECT_LOCK(obj); - vm_object_set_flag(obj, OBJ_ONEMAPPING); - VM_OBJECT_UNLOCK(obj); - end else - if (ref=0) then - if ((obj^.flags and OBJ_DEAD)=0) then - begin - VM_OBJECT_LOCK(obj); - vm_object_terminate(obj); - end; + if (obj^.otype=OBJT_VNODE) then + begin + restart: + + vp:=obj^.handle; + + vfslocked:=0; + if VFS_NEEDSGIANT(vp^.v_mount) then + begin + vfslocked:=1; + if not mtx_trylock(VFS_Giant) then + begin + VM_OBJECT_UNLOCK(obj); + mtx_lock(VFS_Giant); + goto restart; + end; + end; + + vm_object_vndeallocate(obj); + VFS_UNLOCK_GIANT(vfslocked); + Exit; + end; + + Dec(obj^.ref_count); + + if (obj^.ref_count=1) then + begin + vm_object_set_flag(obj, OBJ_ONEMAPPING); + end else + if (obj^.ref_count=0) then + if ((obj^.flags and OBJ_DEAD)=0) then + begin + vm_object_terminate(obj); + end; + + VM_OBJECT_UNLOCK(obj); end; procedure vm_object_pip_wakeup(obj:vm_object_t); @@ -166,7 +256,7 @@ begin end; end; -procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar); +procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar); public; begin if (obj=nil) then Exit; diff --git a/sys/vm/vm_pager.pas b/sys/vm/vm_pager.pas index 1719b8a4..9ee406ff 100644 --- a/sys/vm/vm_pager.pas +++ b/sys/vm/vm_pager.pas @@ -21,7 +21,8 @@ implementation uses vmparam, - device_pager; + device_pager, + vnode_pager; function OFF_TO_IDX(x:QWORD):DWORD; inline; begin @@ -37,7 +38,7 @@ begin case otype of OBJT_DEFAULT :Result:=vm_object_allocate(otype,OFF_TO_IDX(size)); //OBJT_SWAP :; - //OBJT_VNODE :; + OBJT_VNODE :Result:=vnode_pager_alloc(handle,size,prot,off); OBJT_DEVICE :Result:=dev_pager_alloc(handle,size,prot,off); //OBJT_PHYS :; //OBJT_DEAD :; @@ -65,7 +66,7 @@ begin case obj^.otype of OBJT_DEFAULT :default_dealloc(obj); OBJT_SWAP :; - OBJT_VNODE :; + OBJT_VNODE :vnode_pager_dealloc(obj); OBJT_DEVICE :dev_pager_dealloc(obj); OBJT_PHYS :; OBJT_DEAD :; diff --git a/sys/vm/vnode_pager.pas b/sys/vm/vnode_pager.pas new file mode 100644 index 00000000..2070e21b --- /dev/null +++ b/sys/vm/vnode_pager.pas @@ -0,0 +1,325 @@ +unit vnode_pager; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + vnode, + vm, + vmparam, + sys_vm_object; + +function vnode_pager_alloc(handle:Pointer; + size:vm_ooffset_t; + prot:vm_prot_t; + offset:vm_ooffset_t):vm_object_t; + +function vnode_create_vobject(vp:p_vnode;isize:vm_ooffset_t):Integer; + +procedure vnode_destroy_vobject(vp:p_vnode); + +procedure vnode_pager_dealloc(obj:vm_object_t); + +procedure vnode_pager_setsize(vp:p_vnode;nsize:vm_ooffset_t); + +implementation + +uses + vnode_if, + vfs_subr, + vfs_vnops, + kern_synch, + kern_param, + kern_mtx; + +// + +procedure vm_object_terminate(obj:vm_object_t); external; +procedure vm_pager_deallocate(obj:vm_object_t); external; +procedure vm_object_pip_wait(obj:vm_object_t;waitid:pchar); external; + +// + +function IDX_TO_OFF(x:DWORD):QWORD; inline; +begin + Result:=QWORD(x) shl PAGE_SHIFT; +end; + +function OFF_TO_IDX(x:QWORD):DWORD; inline; +begin + Result:=QWORD(x) shr PAGE_SHIFT; +end; + +{ + * Allocate (or lookup) pager for a vnode. + * Handle is a vnode pointer. + * + * MPSAFE + } + +function vnode_pager_alloc(handle:Pointer; + size:vm_ooffset_t; + prot:vm_prot_t; + offset:vm_ooffset_t):vm_object_t; +label + retry; +var + obj:vm_object_t; + vp:p_vnode; +begin + { + * Pageout to vnode, no can do yet. + } + if (handle=nil) then Exit(nil); + + vp:=handle; + + { + * If the obj is being terminated, wait for it to + * go away. + } +retry: + obj:=vp^.v_object; + while (obj<>nil) do + begin + VM_OBJECT_LOCK(obj); + if ((obj^.flags and OBJ_DEAD)=0) then + begin + break; + end; + vm_object_set_flag(obj, OBJ_DISCONNECTWNT); + msleep(obj, VM_OBJECT_MTX(obj), PDROP or PVM, 'vadead', 0); + obj:=vp^.v_object; + end; + + Assert(vp^.v_usecount<>0, 'vnode_pager_alloc: no vnode reference'); + + if (obj=nil) then + begin + { + * Add an obj of the appropriate size + } + obj:=vm_object_allocate(OBJT_VNODE, OFF_TO_IDX(round_page(size))); + + obj^.un_pager.vnp.vnp_size:=size; + obj^.un_pager.vnp.writemappings:=0; + + obj^.handle:=handle; + + VI_LOCK(vp); + if (vp^.v_object<>nil) then + begin + // Obj has been created while we were sleeping + VI_UNLOCK(vp); + VM_OBJECT_LOCK(obj); + Assert(obj^.ref_count=1, 'leaked ref %p %d'); + + obj^.otype:=OBJT_DEAD; + obj^.ref_count:=0; + VM_OBJECT_UNLOCK(obj); + vm_object_destroy(obj); + goto retry; + end; + + vp^.v_object:=obj; + VI_UNLOCK(vp); + end else + begin + Inc(obj^.ref_count); + VM_OBJECT_UNLOCK(obj); + end; + + vref(vp); + Exit(obj); +end; + +{ Create the VM system backing object for this vnode } +function vnode_create_vobject(vp:p_vnode;isize:vm_ooffset_t):Integer; +var + obj:vm_object_t; + size:QWORD; + va:t_vattr; +begin + size:=isize; + + if (not vn_isdisk(vp, nil)) and (vn_canvmio(vp)=FALSE) then + begin + Exit(0); + end; + + obj:=vp^.v_object; + while (obj<>nil) do + begin + VM_OBJECT_LOCK(obj); + if ((obj^.flags and OBJ_DEAD)=0) then + begin + VM_OBJECT_UNLOCK(obj); + Exit(0); + end; + VOP_UNLOCK(vp, 0); + vm_object_set_flag(obj, OBJ_DISCONNECTWNT); + msleep(obj, VM_OBJECT_MTX(obj), PDROP or PVM, 'vodead', 0); + vn_lock(vp, LK_EXCLUSIVE or LK_RETRY); + // + obj:=vp^.v_object; + end; + + if (size=0) then + begin + if (vn_isdisk(vp, nil)) then + begin + size:=IDX_TO_OFF(High(Integer)); + end else + begin + if (VOP_GETATTR(vp, @va)<>0) then + begin + Exit(0); + end; + size:=va.va_size; + end; + end; + + obj:=vnode_pager_alloc(vp, size, 0, 0); + + { + * Dereference the reference we just created. This assumes + * that the obj is associated with the vp. + } + //VM_OBJECT_LOCK(obj); + // Dec(obj^.ref_count); + //VM_OBJECT_UNLOCK(obj); + + //vrele(vp); + + Assert(vp^.v_object<>nil, 'vnode_create_vobject: nil obj'); + + Exit(0); +end; + +procedure vnode_destroy_vobject(vp:p_vnode); +var + obj:vm_object_t; +begin + obj:=vp^.v_object; + if (obj=nil) then Exit; + + ASSERT_VOP_ELOCKED(vp, 'vnode_destroy_vobject'); + + VM_OBJECT_LOCK(obj); + if (obj^.ref_count=0) then + begin + { + * vclean() may be called twice. The first time + * removes the primary reference to the object, + * the second time goes one further and is a + * special-case to terminate the object. + * + * don't double-terminate the object + } + if ((obj^.flags and OBJ_DEAD)=0) then + vm_object_terminate(obj) + else + VM_OBJECT_UNLOCK(obj); + + end else + begin + { + * Woe to the process that tries to page now :-). + } + vm_pager_deallocate(obj); + VM_OBJECT_UNLOCK(obj); + end; + vp^.v_object:=nil; +end; + + +{ + * The object must be locked. + } +procedure vnode_pager_dealloc(obj:vm_object_t); +var + vp:p_vnode; + refs:Integer; +begin + vp:=obj^.handle; + + if (vp=nil) then + begin + Writeln(StdErr,'vnode_pager_dealloc: pager already dealloced'); + Exit; + end; + + VM_OBJECT_LOCK_ASSERT(obj); + vm_object_pip_wait(obj, 'vnpdea'); + refs:=obj^.ref_count; + + obj^.handle:=nil; + obj^.otype:=OBJT_DEAD; + + if ((obj^.flags and OBJ_DISCONNECTWNT)<>0) then + begin + vm_object_clear_flag(obj, OBJ_DISCONNECTWNT); + wakeup(obj); + end; + + ASSERT_VOP_ELOCKED(vp, 'vnode_pager_dealloc'); + + if (obj^.un_pager.vnp.writemappings > 0) then + begin + obj^.un_pager.vnp.writemappings:=0; + VOP_ADD_WRITECOUNT(vp, -1); + end; + vp^.v_object:=nil; + //VOP_UNSET_TEXT(vp); + VM_OBJECT_UNLOCK(obj); + + while (refs>0) do + begin + vunref(vp); + Dec(refs); + end; + + VM_OBJECT_LOCK(obj); +end; + +{ + Lets the VM system know about a change in size for a file. + We adjust our own internal size and flush any cached pages in + the associated object that are affected by the size change. + + Note: this routine may be invoked as a result of a pager put + operation (possibly at object termination time), so we must be careful. +} +procedure vnode_pager_setsize(vp:p_vnode;nsize:vm_ooffset_t); +var + obj:vm_object_t; + nobjsize:DWORD; +begin + obj:=vp^.v_object; + if (obj=nil) then Exit; + + nobjsize:=OFF_TO_IDX(nsize + PAGE_MASK); + + VM_OBJECT_LOCK(obj); + + if (obj^.otype=OBJT_DEAD) then + begin + VM_OBJECT_UNLOCK(obj); + Exit; + end; + + Assert(obj^.otype=OBJT_VNODE,'not vnode-backed obj %p'); + + obj^.un_pager.vnp.vnp_size:=nsize; + obj^.size:=nobjsize; + + VM_OBJECT_UNLOCK(obj); +end; + + +end. + + +