diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas index 8c4f1b3c..15ce4562 100644 --- a/sys/kern/kern_thr.pas +++ b/sys/kern/kern_thr.pas @@ -388,13 +388,18 @@ var td:p_kthread; begin td:=curkthread; + if (td=nil) then Exit; Result:=(not flags) or (td^.td_pflags and flags); td^.td_pflags:=td^.td_pflags or flags; end; procedure curthread_pflags_restore(save:Integer); +var + td:p_kthread; begin - curkthread^.td_pflags:=curkthread^.td_pflags and save; + td:=curkthread; + if (td=nil) then Exit; + td^.td_pflags:=td^.td_pflags and save; end; // diff --git a/sys/kern/kern_time.pas b/sys/kern/kern_time.pas index 7d6eaa5c..3a79941f 100644 --- a/sys/kern/kern_time.pas +++ b/sys/kern/kern_time.pas @@ -10,10 +10,6 @@ uses ntapi, time; -procedure timevalfix(t1:ptimeval); -procedure timevaladd(t1,t2:ptimeval); -procedure timevalsub(t1,t2:ptimeval); - function cputick2usec(time:QWORD):QWORD; inline; function get_unit_uptime:Int64; procedure getmicrouptime(tvp:ptimeval); @@ -40,34 +36,6 @@ Const POW10_7 =10000000; POW10_9 =1000000000; -procedure timevalfix(t1:ptimeval); -begin - if (t1^.tv_usec < 0) then - begin - Dec(t1^.tv_sec); - Inc(t1^.tv_usec,1000000); - end; - if (t1^.tv_usec >= 1000000) then - begin - Inc(t1^.tv_sec); - Dec(t1^.tv_usec,1000000); - end; -end; - -procedure timevaladd(t1,t2:ptimeval); -begin - Inc(t1^.tv_sec ,t2^.tv_sec); - Inc(t1^.tv_usec,t2^.tv_usec); - timevalfix(t1); -end; - -procedure timevalsub(t1,t2:ptimeval); -begin - Dec(t1^.tv_sec ,t2^.tv_sec); - Dec(t1^.tv_usec,t2^.tv_usec); - timevalfix(t1); -end; - function cputick2usec(time:QWORD):QWORD; inline; begin Result:=time div 10; diff --git a/sys/kern/systm.pas b/sys/kern/systm.pas index cee3a98b..4d583b88 100644 --- a/sys/kern/systm.pas +++ b/sys/kern/systm.pas @@ -12,6 +12,7 @@ const IOSIZE_MAX =High(Int64); DEVFS_IOSIZE_MAX=High(Int64); +function copystr(from,_to:Pointer;maxlen:ptruint;lencopied:pptruint):Integer; function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline; function copyinstr(udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer; function copyout(kaddr,udaddr:Pointer;len:ptruint):Integer; inline; @@ -26,8 +27,19 @@ function suword64(var base:QWORD;word:QWORD):DWORD; inline; implementation uses + sysutils, errno; +function copystr(from,_to:Pointer;maxlen:ptruint;lencopied:pptruint):Integer; +begin + strlcopy(_to,from,maxlen); + if (lencopied<>nil) then + begin + lencopied^:=strlen(_to); + end; + Result:=0; +end; + function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline; begin if (NtReadVirtualMemory(NtCurrentProcess,udaddr,kaddr,len,nil)=0) then diff --git a/sys/sys_sysinit.pas b/sys/sys_sysinit.pas index 46b9e566..4bbd9a54 100644 --- a/sys/sys_sysinit.pas +++ b/sys/sys_sysinit.pas @@ -30,7 +30,8 @@ uses devfs, devfs_devs, devfs_vfsops, - kern_descrip; + kern_descrip, + vfs_mountroot; //Daemon for a separate thread procedure sys_update; @@ -41,6 +42,7 @@ end; procedure module_init; begin vfs_register(@devfs_vfsconf); + vfs_mountroot.vfs_mountroot(); end; //Manual order of lazy initialization diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 99de4ea9..99e1dbdf 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -441,6 +441,10 @@ + + + + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index e9ac1297..97214612 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -1,6 +1,7 @@ uses windows, + dateutils, atomic, ntapi, mqueue, @@ -53,7 +54,11 @@ uses sys_fnmatch, devfs, devfs_vfsops, - devfs_vnops; + devfs_vnops, + vfs_mountroot, + vstat, + vfcntl, + vdirent; var mtx:umutex; @@ -223,6 +228,96 @@ var ymm0:array[0..31] of Byte=(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1); ymm0_ptr:Pointer=@ymm0; +function ts_to_str(ts:timespec):RawByteString; +var + D:TDateTime; +begin + D:=UnixToDateTime(ts.tv_sec); + D:=UniversalTimeToLocal(D); + Result:=DateTimeToStr(D); +end; + +function IncludeUnixTrailing(Const Path:RawByteString):RawByteString; +Var + L:Integer; +begin + Result:=Path; + L:=Length(Result); + If (L=0) or (Path[L]<>'/') then + begin + SetLength(Result,L+1); + Result[L+1]:='/'; + end; +end; + +procedure test_dirs(const p:RawByteString;s:Byte); +var + td:p_kthread; + sb:t_stat; + buf:array[0..511] of Byte; + dir:p_dirent; + fd:Integer; + err:Integer; + c:Integer; +begin + td:=curkthread; + err:=sys_stat(PChar(p),@sb); + if (err<>0) then + begin + Writeln(Space(s),p,' | (',err,')'); + end else + begin + Write(Space(s),p,' | ',ts_to_str(sb.st_mtim),' |'); + + if ((sb.st_mode and S_IFDIR)<>0) then + begin + Write(' DIR'); + Assert(sb.st_size=512); + + fd:=sys_open(PChar(p),O_RDONLY or O_DIRECTORY,0); + + if (fd<0) then + begin + Write(' | (',fd,')'); + Exit; + end else + begin + Writeln; + end; + Writeln(Space(s),'->'); + + repeat + FillChar(buf,512,0); + dir:=@buf; + err:=sys_getdents(fd,dir,512); + if (err<0) then Break; + + c:=td^.td_retval[0]; + if (c=0) then Break; + + while (dir<(@buf+c)) do + begin + case RawByteString(dir^.d_name) of + '.':; + '..':; + else + //Writeln(dir^.d_name); + test_dirs(IncludeUnixTrailing(p)+RawByteString(dir^.d_name),s+1); + end; + + PByte(dir):=PByte(dir)+dir^.d_reclen; + end; + + until false; + + Writeln(Space(s),'<-'); + end else + begin + Writeln(' ',sb.st_size); + end; + end; +end; + procedure test_thread; sysv_abi_default; var rax:qword; @@ -236,6 +331,10 @@ begin if (tid<>curkthread^.td_tid) then begin + Writeln('[--test_dirs--]'); + test_dirs('/',1); + Writeln('[--test_dirs--]'); + tid2:=curkthread^.td_tid; evf:=evf_create('evf test',EVF_ATTR_TH_PRIO,0); diff --git a/sys/time.pas b/sys/time.pas index 659382b8..22e8fd99 100644 --- a/sys/time.pas +++ b/sys/time.pas @@ -65,6 +65,10 @@ function _nsec2usec(nsec:QWORD):QWORD; //Nanosecond to Microsecond function _msec2nsec(msec:QWORD):QWORD; //Milisecond to Nanosecond function _nsec2msec(nsec:QWORD):QWORD; //Nanosecond to Milisecond +procedure timevalfix(t1:ptimeval); +procedure timevaladd(t1,t2:ptimeval); +procedure timevalsub(t1,t2:ptimeval); + function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline; procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec); inline; @@ -126,6 +130,34 @@ begin Result:=(nsec+999999) div 1000000; end; +procedure timevalfix(t1:ptimeval); +begin + if (t1^.tv_usec < 0) then + begin + Dec(t1^.tv_sec); + Inc(t1^.tv_usec,1000000); + end; + if (t1^.tv_usec >= 1000000) then + begin + Inc(t1^.tv_sec); + Dec(t1^.tv_usec,1000000); + end; +end; + +procedure timevaladd(t1,t2:ptimeval); +begin + Inc(t1^.tv_sec ,t2^.tv_sec); + Inc(t1^.tv_usec,t2^.tv_usec); + timevalfix(t1); +end; + +procedure timevalsub(t1,t2:ptimeval); +begin + Dec(t1^.tv_sec ,t2^.tv_sec); + Dec(t1^.tv_usec,t2^.tv_usec); + timevalfix(t1); +end; + function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline; begin if (tvp^.tv_sec=uvp^.tv_sec) then diff --git a/sys/vfs/subr_uio.pas b/sys/vfs/subr_uio.pas index 3aea6be0..d2c4462a 100644 --- a/sys/vfs/subr_uio.pas +++ b/sys/vfs/subr_uio.pas @@ -58,7 +58,7 @@ begin end; save:=curthread_pflags_set(newflags); - while (n > 0 and uio^.uio_resid) do + while (n > 0) and (uio^.uio_resid<>0) do begin iov:=uio^.uio_iov; cnt:=iov^.iov_len; @@ -88,17 +88,16 @@ begin Move(cp^, iov^.iov_base^, cnt) else Move(iov^.iov_base^, cp^, cnt); - break; end; UIO_NOCOPY:; else; end; - iov^.iov_base:=iov^.iov_base + cnt; - Dec(iov^.iov_len,cnt); - Dec(uio^.uio_resid,cnt); + Inc(iov^.iov_base ,cnt); + Dec(iov^.iov_len ,cnt); + Dec(uio^.uio_resid ,cnt); Inc(uio^.uio_offset,cnt); - cp:=cp + cnt; + Inc(cp,cnt); Dec(n,cnt); end; diff --git a/sys/vfs/vfs_default.pas b/sys/vfs/vfs_default.pas index 5b59f9ee..9aa78c77 100644 --- a/sys/vfs/vfs_default.pas +++ b/sys/vfs/vfs_default.pas @@ -528,6 +528,42 @@ begin { NOTREACHED } end; +function lockmgr(lk:p_mtx;flags:Integer;ilk:p_mtx):Integer; +var + op:Integer; +begin + + op:=(flags and LK_TYPE_MASK); + case op of + LK_SHARED, + LK_EXCLUSIVE: + begin + mtx_lock(lk^); + end; + LK_RELEASE: + begin + mtx_unlock(lk^); + end; + LK_UPGRADE: + begin + if not mtx_owned(lk^) then + begin + mtx_lock(lk^); + end; + end; + LK_DOWNGRADE:;// + else + Assert(false); + end; + + if ((flags and LK_INTERLOCK)<>0) then + begin + mtx_unlock(ilk^); + end; + + Result:=0; +end; + { * Standard lock, unlock and islocked functions. } @@ -537,14 +573,7 @@ var begin vp:=ap^.a_vp; - if (ap^.a_flags and LK_INTERLOCK)<>0 then - begin - mtx_unlock(VI_MTX(vp)^); - Exit(0); - end; - - mtx_lock(vp^.v_vnlock^); - Exit(0); + Result:=lockmgr(vp^.v_vnlock,ap^.a_flags,VI_MTX(vp)); //Exit(_lockmgr_args(vp^.v_vnlock, ap^.a_flags, VI_MTX(vp), // LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap^.a_file, @@ -558,14 +587,7 @@ var begin vp:=ap^.a_vp; - if (ap^.a_flags and LK_INTERLOCK)<>0 then - begin - mtx_unlock(VI_MTX(vp)^); - Exit(0); - end; - - mtx_unlock(vp^.v_vnlock^); - Exit(0); + Result:=lockmgr(vp^.v_vnlock,ap^.a_flags or LK_RELEASE,VI_MTX(vp)); //Exit(lockmgr(vp^.v_vnlock, ap^.a_flags or LK_RELEASE, VI_MTX(vp))); end; @@ -778,7 +800,7 @@ var off:QWORD; fileno:DWORD; va:t_vattr; - nd:nameidata; + nd:t_nameidata; td:p_kthread; dp:p_dirent; mvp:p_vnode; diff --git a/sys/vfs/vfs_lookup.pas b/sys/vfs/vfs_lookup.pas index 188c0ec9..0fe08423 100644 --- a/sys/vfs/vfs_lookup.pas +++ b/sys/vfs/vfs_lookup.pas @@ -67,7 +67,7 @@ end; * if symbolic link, massage name in buffer and continue * end; } -procedure namei_cleanup_cnp(cnp:p_componentname); +procedure namei_cleanup_cnp(cnp:p_componentname); inline; begin FreeMem(cnp^.cn_pnbuf); end; @@ -92,10 +92,10 @@ begin cnp:=@ndp^.ni_cnd; td:=cnp^.cn_thread; - Assert(((cnp^.cn_flags and MPSAFE)<>0) or mtx_owned(VFS_Giant),('NOT MPSAFE and Giant not held')); + Assert(((cnp^.cn_flags and MPSAFE)<>0) or mtx_owned(VFS_Giant),'NOT MPSAFE and Giant not held'); Assert((cnp^.cn_nameiop and (not OPMASK))=0,'namei: nameiop contaminated with flags'); - Assert((cnp^.cn_flags and OPMASK)=0,('namei: flags contaminated with nameiops')); + Assert((cnp^.cn_flags and OPMASK)=0,'namei: flags contaminated with nameiops'); if (lookup_shared=0) then cnp^.cn_flags:=cnp^.cn_flags and (not LOCKSHARED); @@ -113,8 +113,7 @@ begin if (ndp^.ni_segflg=UIO_SYSSPACE) then begin - ndp^.ni_pathlen:=strlcopy(ndp^.ni_dirp,cnp^.cn_pnbuf,MAXPATHLEN)-ndp^.ni_dirp; - error:=0; + error:=copystr(ndp^.ni_dirp, cnp^.cn_pnbuf, MAXPATHLEN, @ndp^.ni_pathlen); end else begin error:=copyinstr(ndp^.ni_dirp, cnp^.cn_pnbuf, MAXPATHLEN, @ndp^.ni_pathlen); @@ -141,14 +140,6 @@ begin ndp^.ni_rootdir:=fdp^.fd_rdir; ndp^.ni_topdir:=fdp^.fd_jdir; - { - * If we are auditing the kernel pathname, save the user pathname. - } - //if ((cnp^.cn_flags and AUDITVNODE1)<>0) then - // AUDIT_ARG_UPATH1(td, ndp^.ni_dirfd, cnp^.cn_pnbuf); - //if ((cnp^.cn_flags and AUDITVNODE2)<>0) then - // AUDIT_ARG_UPATH2(td, ndp^.ni_dirfd, cnp^.cn_pnbuf); - dp:=nil; if (cnp^.cn_pnbuf[0]<>'/') then begin @@ -159,13 +150,10 @@ begin end else if (ndp^.ni_dirfd<>AT_FDCWD) then begin - //if (cnp^.cn_flags and AUDITVNODE1) - // AUDIT_ARG_ATFD1(ndp^.ni_dirfd); - //if (cnp^.cn_flags and AUDITVNODE2) - // AUDIT_ARG_ATFD2(ndp^.ni_dirfd); error:=fgetvp_rights(ndp^.ni_dirfd, - ndp^.ni_rightsneeded or CAP_LOOKUP, - @ndp^.ni_baserights, @dp); + ndp^.ni_rightsneeded or CAP_LOOKUP, + @ndp^.ni_baserights, + @dp); end; if (error<>0) or (dp<>nil) then @@ -276,15 +264,16 @@ begin else cp:=cnp^.cn_pnbuf; - aiov.iov_base:=cp; - aiov.iov_len:=MAXPATHLEN; - auio.uio_iov:=@aiov; + aiov.iov_base :=cp; + aiov.iov_len :=MAXPATHLEN; + auio.uio_iov :=@aiov; auio.uio_iovcnt:=1; auio.uio_offset:=0; - auio.uio_rw:=UIO_READ; + auio.uio_rw :=UIO_READ; auio.uio_segflg:=UIO_SYSSPACE; - auio.uio_td:=td; - auio.uio_resid:=MAXPATHLEN; + auio.uio_td :=td; + auio.uio_resid :=MAXPATHLEN; + error:=VOP_READLINK(ndp^.ni_vp, @auio); if (error<>0) then begin @@ -313,8 +302,8 @@ begin FreeMem(cnp^.cn_pnbuf); cnp^.cn_pnbuf:=cp; end else - cnp^.cn_pnbuf[linklen]:='0'; - ndp^.ni_pathlen += linklen; + cnp^.cn_pnbuf[linklen]:=#0; + Inc(ndp^.ni_pathlen,linklen); vput(ndp^.ni_vp); dp:=ndp^.ni_dvp; end; @@ -459,7 +448,7 @@ begin (cnp^.cn_nameiop<>LOOKUP)) then docache:=0; _rdonly:=cnp^.cn_flags and RDONLY; - cnp^.cn_flags:= cnp^.cn_flags and (not ISSYMLINK); + cnp^.cn_flags:=cnp^.cn_flags and (not ISSYMLINK); ndp^.ni_dvp:=nil; { * We use shared locks until we hit the parent of the last cn then @@ -567,12 +556,6 @@ dirloop: end; ndp^.ni_vp:=dp; - //if (cnp^.cn_flags and AUDITVNODE1) then - // AUDIT_ARG_VNODE1(dp); - //else - //if (cnp^.cn_flags and AUDITVNODE2) then - // AUDIT_ARG_VNODE2(dp); - if ((cnp^.cn_flags and (LOCKPARENT or LOCKLEAF))=0) then VOP_UNLOCK(dp, 0); { XXX This should probably move to the top of function. } @@ -669,6 +652,7 @@ unionlookup: (VOP_ISLOCKED(dp)=LK_SHARED) and ((cnp^.cn_flags and ISLASTCN)<>0) and ((cnp^.cn_flags and LOCKPARENT)<>0) then vn_lock(dp, LK_UPGRADE or LK_RETRY); + if ((dp^.v_iflag and VI_DOOMED)<>0) then begin error:=ENOENT; @@ -893,13 +877,9 @@ nextname: ni_dvp_unlocked:=1; end; - //if (cnp^.cn_flags and AUDITVNODE1) then - // AUDIT_ARG_VNODE1(dp); - //else if (cnp^.cn_flags and AUDITVNODE2) then - // AUDIT_ARG_VNODE2(dp); - if ((cnp^.cn_flags and LOCKLEAF)=0) then VOP_UNLOCK(dp, 0); + success: { * Because of lookup_shared we may have the vnode shared locked, but diff --git a/sys/vfs/vfs_mount.pas b/sys/vfs/vfs_mount.pas index e8334e08..afc91942 100644 --- a/sys/vfs/vfs_mount.pas +++ b/sys/vfs/vfs_mount.pas @@ -33,6 +33,22 @@ const nil ); +type + { A memory allocation which must be freed when we are done } + p_mntaarg=^t_mntaarg; + t_mntaarg=packed record + next:SLIST_ENTRY; //mntaarg + end; + + { The header for the mount arguments } + p_mntarg=^t_mntarg; + t_mntarg=packed record + v:p_iovec; + len:Integer; + error:Integer; + list:SLIST_HEAD; //mntaarg + end; + procedure vfs_freeopt(opts:p_vfsoptlist;opt:p_vfsopt); procedure vfs_freeopts(opts:p_vfsoptlist); procedure vfs_deleteopt(opts:p_vfsoptlist;name:PChar); @@ -77,6 +93,13 @@ function vfs_donmount(fsflags:QWORD;fsoptions:p_uio):Integer; function dounmount(mp:p_mount;flags:Integer):Integer; +function mount_argb(ma:p_mntarg;flag:Integer;name:PChar):p_mntarg; +function mount_argf(ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register; +function mount_argsu(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; +function mount_arg(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; +procedure free_mntarg(ma:p_mntarg); +function kernel_mount(ma:p_mntarg;flags:QWORD):Integer; + implementation uses @@ -211,12 +234,12 @@ begin begin if (vfs_equalopts(opt^.name, opt2^.name)<>0) then begin - tmp:=TAILQ_PREV(opt2,@opt^.link); + tmp:=TAILQ_PREV(opt2,@opt2^.link); vfs_freeopt(opts, opt2); opt2:=tmp; end else begin - opt2:=TAILQ_PREV(opt2,@opt^.link); + opt2:=TAILQ_PREV(opt2,@opt2^.link); end; end; // @@ -643,7 +666,8 @@ end; function strlcpy(dst,src:PChar;size:ptrint):ptrint; inline; begin - Result:=strlcopy(dst,src,size)-dst; + strlcopy(dst,src,size); + Result:=strlen(dst); end; function vfs_setopts(opts:p_vfsoptlist;name,value:PChar):Integer; @@ -720,11 +744,11 @@ begin mp^.mnt_stat.f_type:=vfsp^.vfc_typenum; Inc(mp^.mnt_gen); - strlcopy(mp^.mnt_stat.f_fstypename, vfsp^.vfc_name, MFSNAMELEN); + strlcopy(@mp^.mnt_stat.f_fstypename, @vfsp^.vfc_name, MFSNAMELEN); mp^.mnt_vnodecovered:=vp; - strlcopy(mp^.mnt_stat.f_mntonname, fspath, MNAMELEN); + strlcopy(@mp^.mnt_stat.f_mntonname, fspath, MNAMELEN); mp^.mnt_iosize_max:=DFLTPHYS; @@ -941,7 +965,7 @@ begin VI_UNLOCK(vp); vfs_unbusy(mp); vput(vp); - Exit (EBUSY); + Exit(EBUSY); end; vp^.v_iflag:=vp^.v_iflag or VI_MOUNT; VI_UNLOCK(vp); @@ -951,6 +975,7 @@ begin mp^.mnt_flag:=mp^.mnt_flag and (not MNT_UPDATEMASK); mp^.mnt_flag:=(mp^.mnt_flag or fsflags) and (MNT_RELOAD or MNT_FORCE or MNT_UPDATE or MNT_SNAPSHOT or MNT_ROOTFS or MNT_UPDATEMASK or MNT_RDONLY); + if ((mp^.mnt_flag and MNT_ASYNC)=0) then mp^.mnt_kern_flag:=mp^.mnt_kern_flag and (not MNTK_ASYNC); MNT_IUNLOCK(mp); @@ -1050,7 +1075,7 @@ function vfs_domount(fstype:PChar; { Filesystem type. } ):Integer; var vfsp:p_vfsconf; - nd:nameidata; + nd:t_nameidata; vp:p_vnode; pathbuf:PChar; error:Integer; @@ -1462,6 +1487,153 @@ begin Exit(0); end; +{ + * Add a boolean argument. + * + * flag is the boolean value. + * name must start with 'no'. + } +function mount_argb(ma:p_mntarg;flag:Integer;name:PChar):p_mntarg; +begin + Assert((name[0]='n') and (name[1]='o'),'mount_argb(...,%s): name must start with no'); + + Exit(mount_arg(ma, name + (ord(flag<>0)*2), nil, 0)); +end; + +{ + * Add an argument printf style + } +function mount_argf(ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register; +var + maa:p_mntaarg; + len:Integer; + sb:RawByteString; +begin + if (ma=nil) then + begin + ma:=AllocMem(sizeof(t_mntarg)); + SLIST_INIT(@ma^.list); + end; + if (ma^.error<>0) then + Exit(ma); + + ma^.v:=ReAllocMem(ma^.v, sizeof(iovec) * (ma^.len + 2)); + ma^.v[ma^.len].iov_base:=name; + ma^.v[ma^.len].iov_len :=strlen(name) + 1; + Inc(ma^.len); + + sb:=Format(fmt,Args); + len:=Length(sb) + 1; + maa:=AllocMem(sizeof(t_mntaarg) + len); + SLIST_INSERT_HEAD(@ma^.list,maa,@maa^.next); + Move(PChar(sb)^, (maa + 1)^, len); + + ma^.v[ma^.len].iov_base:=maa + 1; + ma^.v[ma^.len].iov_len :=len; + Inc(ma^.len); + + Exit(ma); +end; + +{ + * Add an argument which is a userland string. + } +function mount_argsu(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; +var + maa:p_mntaarg; + tbuf:Pointer; +begin + if (val=nil) then + Exit(ma); + if (ma=nil) then + begin + ma:=AllocMem(sizeof(t_mntarg)); + SLIST_INIT(@ma^.list); + end; + if (ma^.error<>0) then + Exit(ma); + maa:=AllocMem(sizeof(t_mntaarg) + len); + SLIST_INSERT_HEAD(@ma^.list,maa,@maa^.next); + tbuf:=Pointer(maa + 1); + ma^.error:=copyinstr(val, tbuf, len, nil); + Exit(mount_arg(ma, name, tbuf, -1)); +end; + +{ + * Plain argument. + * + * If length is -1, treat value as a C string. + } +function mount_arg(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; +begin + if (ma=nil) then + begin + ma:=AllocMem(sizeof(t_mntarg)); + SLIST_INIT(@ma^.list); + end; + if (ma^.error<>0) then + Exit(ma); + + ma^.v:=ReAllocMem(ma^.v, sizeof(iovec) * (ma^.len + 2)); + ma^.v[ma^.len].iov_base:=name; + ma^.v[ma^.len].iov_len :=strlen(name) + 1; + Inc(ma^.len); + + ma^.v[ma^.len].iov_base:=val; + if (len < 0) then + ma^.v[ma^.len].iov_len:=strlen(val) + 1 + else + ma^.v[ma^.len].iov_len:=len; + Inc(ma^.len); + + Exit(ma); +end; + +{ + * Free a mntarg structure + } +procedure free_mntarg(ma:p_mntarg); +var + maa:p_mntaarg; +begin + while (not SLIST_EMPTY(@ma^.list)) do + begin + maa:=SLIST_FIRST(@ma^.list); + SLIST_REMOVE_HEAD(@ma^.list,@p_mntaarg(nil)^.next); + FreeMem(maa); + end; + FreeMem(ma^.v); + FreeMem(ma); +end; + +{ + * Mount a filesystem + } +function kernel_mount(ma:p_mntarg;flags:QWORD):Integer; +var + auio:t_uio; + error:Integer; +begin + Assert(ma<>nil, 'kernel_mount nil ma'); + Assert(ma^.v<>nil, 'kernel_mount nil ma^.v'); + Assert((ma^.len and 1)=0, 'kernel_mount odd ma^.len (%d)'); + + auio.uio_iov:=ma^.v; + auio.uio_iovcnt:=ma^.len; + auio.uio_segflg:=UIO_SYSSPACE; + + error:=ma^.error; + if (error=0) then + error:=vfs_donmount(flags, @auio); + free_mntarg(ma); + Exit(error); +end; + + + + + + end. diff --git a/sys/vfs/vfs_mountroot.pas b/sys/vfs/vfs_mountroot.pas new file mode 100644 index 00000000..7b30287e --- /dev/null +++ b/sys/vfs/vfs_mountroot.pas @@ -0,0 +1,349 @@ +unit vfs_mountroot; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + mqueue, + vmount; + +procedure vfs_mountroot(); +function vfs_mountroot_simple(fstype,fspath,from,opts:PChar):Integer; + +implementation + +uses + sysutils, + errno, + vuio, + vnamei, + vfs_vnode, + vnode_if, + vfiledesc, + vfs_subr, + vfs_init, + vfs_mount, + vfs_syscalls, + vfs_lookup, + kern_thr, + kern_mtx; + +function strdup(src:PChar):PChar; inline; +var + i:ptrint; +begin + i:=strlen(src); + Result:=AllocMem(i+1); + Move(src^,Result^,i); +end; + +function strsep(stringp:PPChar;delim:PChar):PChar; +var + b,e:PChar; +begin + b:=stringp^; + if (b=nil) then Exit(nil); + + e:=strpos(b,delim)+strlen(delim); + + if (e^<>#0) then + begin + e^:=#0; + Inc(e); + stringp^:=e; + end else + begin + stringp^:=nil; + end; + + Result:=b; +end; + +function parse_mountroot_options(ma:p_mntarg;options:PChar):p_mntarg; +var + p:PChar; + name,name_arg:PChar; + val,val_arg:PChar; + opts:PChar; +begin + if (options=nil) or (options[0]=#0) then + Exit(ma); + + p:=strdup(options); + opts:=p; + + if (opts=nil) then + begin + Exit(ma); + end; + + name:=strsep(@p, ','); + while (name<>nil) do + begin + if (name[0]=#0) then + break; + + val:=strscan(name, '='); + if (val<>nil) then + begin + val^:=#0; + Inc(val); + end; + + name_arg:=strdup(name); + val_arg:=nil; + + if (val<>nil) then + val_arg:=strdup(val); + + ma:=mount_arg(ma, name_arg, val_arg, (ord(val_arg<>nil)*(-1))); + + name:=strsep(@p, ','); + end; + + FreeMem(opts); + Exit(ma); +end; + +procedure set_rootvnode(); +begin + if (VFS_ROOT(TAILQ_FIRST(@mountlist), LK_EXCLUSIVE, @rootvnode)<>0) then + Assert(False,'Cannot find root vnode'); + + VOP_UNLOCK(rootvnode, 0); + + FILEDESC_XLOCK(@fd_table); + + if (fd_table.fd_cdir<>nil) then + vrele(fd_table.fd_cdir); + + fd_table.fd_cdir:=rootvnode; + VREF(rootvnode); + + if (fd_table.fd_rdir<>nil) then + vrele(fd_table.fd_rdir); + + fd_table.fd_rdir:=rootvnode; + VREF(rootvnode); + + FILEDESC_XUNLOCK(@fd_table); +end; + +function vfs_mountroot_devfs(mpp:pp_mount):Integer; +var + opts:p_vfsoptlist; + vfsp:p_vfsconf; + mp:p_mount; + error:Integer; +begin + mpp^:=nil; + + vfsp:=vfs_byname('devfs'); + Assert(vfsp<>nil,'Could not find devfs by name'); + + if (vfsp=nil) then + Exit(ENOENT); + + mp:=vfs_mount_alloc(nil, vfsp, '/dev'); + + error:=vmount.VFS_MOUNT(mp); + Assert(error=0,'VFS_MOUNT(devfs) failed'); + + if (error<>0) then + Exit(error); + + opts:=AllocMem(sizeof(vfsoptlist)); + TAILQ_INIT(opts); + mp^.mnt_opt:=opts; + + mtx_lock(mountlist_mtx); + TAILQ_INSERT_HEAD(@mountlist,mp,@mp^.mnt_list); + mtx_unlock(mountlist_mtx); + + mpp^:=mp; + set_rootvnode(); + + error:=kern_symlink('/', 'dev', UIO_SYSSPACE); + if (error<>0) then + begin + Writeln('kern_symlink /dev / returns ',error); + end; + + Exit(error); +end; + + +function vfs_mountroot_shuffle(mpdevfs:p_mount):Integer; +var + nd:t_nameidata; + mporoot,mpnroot:p_mount; + vp,vporoot,vpdevfs:p_vnode; + fspath:PChar; + error:Integer; +begin + mpnroot:=TAILQ_NEXT(mpdevfs,@mpdevfs^.mnt_list); + + { Shuffle the mountlist. } + mtx_lock(mountlist_mtx); + mporoot:=TAILQ_FIRST(@mountlist); + TAILQ_REMOVE(@mountlist,mpdevfs,@mpdevfs^.mnt_list); + if (mporoot<>mpdevfs) then + begin + TAILQ_REMOVE(@mountlist,mpnroot,@mpnroot^.mnt_list); + TAILQ_INSERT_HEAD(@mountlist,mpnroot,@mpnroot^.mnt_list); + end; + TAILQ_INSERT_TAIL(@mountlist,mpdevfs,@mpdevfs^.mnt_list); + mtx_unlock(mountlist_mtx); + + //cache_purgevfs(mporoot); + //if (mporoot<>mpdevfs) then + // cache_purgevfs(mpdevfs); + + VFS_ROOT(mporoot, LK_EXCLUSIVE, @vporoot); + + VI_LOCK(vporoot); + vporoot^.v_iflag:=vporoot^.v_iflag and (not VI_MOUNT); + VI_UNLOCK(vporoot); + vporoot^.v_mountedhere:=nil; + mporoot^.mnt_flag:=mporoot^.mnt_flag and (not MNT_ROOTFS); + mporoot^.mnt_vnodecovered:=nil; + vput(vporoot); + + { Set up the new rootvnode, and purge the cache } + mpnroot^.mnt_vnodecovered:=nil; + set_rootvnode(); + //cache_purgevfs(rootvnode^.v_mount); + + if (mporoot<>mpdevfs) then + begin + { Remount old root under /.mount or /mnt } + fspath:='/.mount'; + NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, fspath, curkthread); + error:=_namei(@nd); + if (error<>0) then + begin + NDFREE(@nd, NDF_ONLY_PNBUF); + fspath:='/mnt'; + NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, fspath, curkthread); + error:=_namei(@nd); + end; + if (error=0) then + begin + vp:=nd.ni_vp; + + if (vp^.v_type=VDIR) then + error:=0 + else + error:=ENOTDIR; + + //if (error=0) then + // error:=vinvalbuf(vp, V_SAVE, 0, 0); + + if (error=0) then + begin + //cache_purge(vp); + mporoot^.mnt_vnodecovered:=vp; + vp^.v_mountedhere:=mporoot; + strlcopy(@mporoot^.mnt_stat.f_mntonname, fspath, MNAMELEN); + VOP_UNLOCK(vp, 0); + end else + vput(vp); + end; + NDFREE(@nd, NDF_ONLY_PNBUF); + + if (error<>0) then + Writeln('mountroot: unable to remount previous root under /.mount or /mnt ', error); + end; + + { Remount devfs under /dev } + NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, '/dev', curkthread); + error:=_namei(@nd); + if (error=0) then + begin + vp:=nd.ni_vp; + + if (vp^.v_type=VDIR) then + error:=0 + else + error:=ENOTDIR; + + //if (error=0) then + // error:=vinvalbuf(vp, V_SAVE, 0, 0); + + if (error=0) then + begin + vpdevfs:=mpdevfs^.mnt_vnodecovered; + if (vpdevfs<>nil) then + begin + //cache_purge(vpdevfs); + vpdevfs^.v_mountedhere:=nil; + vrele(vpdevfs); + end; + mpdevfs^.mnt_vnodecovered:=vp; + vp^.v_mountedhere:=mpdevfs; + VOP_UNLOCK(vp, 0); + end else + vput(vp); + end; + if (error<>0) then + Writeln('mountroot: unable to remount devfs under /dev ', error); + + NDFREE(@nd, NDF_ONLY_PNBUF); + + if (mporoot=mpdevfs) then + begin + vfs_unbusy(mpdevfs); + { Unlink the no longer needed /dev/dev ^. / symlink } + error:=kern_unlink('/dev/dev', UIO_SYSSPACE); + if (error<>0) then + Writeln('mountroot: unable to unlink /dev/dev ', error); + end; + + Exit(0); +end; + +function vfs_mountroot_simple(fstype,fspath,from,opts:PChar):Integer; +const + ERRMSGL=255; +var + ma:p_mntarg; + errmsg:RawByteString; +begin + errmsg:=''; + SetLength(errmsg,ERRMSGL); + FillChar(PChar(errmsg)^,ERRMSGL,0); + + if (vfs_byname(fstype)=nil) then + begin + strlcopy(PChar(errmsg),'unknown file system',ERRMSGL); + Exit(ENOENT); + end; + + ma:=nil; + ma:=mount_arg(ma, 'fstype', fstype, -1); + ma:=mount_arg(ma, 'fspath', fspath, -1); + ma:=mount_arg(ma, 'from' , from , -1); + ma:=mount_arg(ma, 'errmsg', PChar(errmsg), ERRMSGL); + + ma:=parse_mountroot_options(ma, opts); + Result:=kernel_mount(ma, MNT_ROOTFS); +end; + +procedure vfs_mountroot(); +var + mp:p_mount; + error:Integer; +begin + error:=vfs_mountroot_devfs(@mp); + + if (error<>0) then + begin + error:=vfs_mountroot_shuffle(mp); + end; + +end; + +end. + diff --git a/sys/vfs/vfs_syscalls.pas b/sys/vfs/vfs_syscalls.pas index fb8a6fda..c09568bf 100644 --- a/sys/vfs/vfs_syscalls.pas +++ b/sys/vfs/vfs_syscalls.pas @@ -79,11 +79,14 @@ function sys_renameat(oldfd:Integer;old:PChar;newfd:Integer;new:PChar):Integer; function sys_mkdir(path:PChar;mode:Integer):Integer; function sys_mkdirat(fd:Integer;path:PChar;mode:Integer):Integer; function sys_rmdir(path:PChar):Integer; -function sys_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer; -function sys_getdents(fd:Integer;buf:PChar;count:DWORD):Integer; +function sys_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer; +function sys_getdents(fd:Integer;buf:Pointer;count:DWORD):Integer; function sys_umask(newmask:Integer):Integer; function sys_revoke(path:PChar):Integer; +function kern_symlink(path,link:PChar;segflg:uio_seg):Integer; +function kern_unlink(path:PChar;pathseg:uio_seg):Integer; + implementation uses @@ -146,7 +149,7 @@ var sb:t_statfs; vfslocked:Integer; error:Integer; - nd:nameidata; + nd:t_nameidata; begin NDINIT(@nd, LOOKUP, FOLLOW or LOCKSHARED or LOCKLEAF or MPSAFE or AUDITVNODE1, pathseg, path, curkthread); error:=_namei(@nd); @@ -496,7 +499,7 @@ end; function kern_chdir(path:PChar;pathseg:uio_seg):Integer; var error:Integer; - nd:nameidata; + nd:t_nameidata; vp:p_vnode; vfslocked:Integer; begin @@ -582,7 +585,7 @@ label e_vunlock; var error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin error:=EPERM; @@ -728,7 +731,7 @@ var nfp:p_file; _type,indx,error,error_open:Integer; lf:t_flock; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; rights_needed:cap_rights_t; begin @@ -925,7 +928,7 @@ var mp:p_mount; vattr:t_vattr; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin restart: @@ -985,7 +988,7 @@ var vattr:t_vattr; error:Integer; whiteout:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin whiteout:=0; @@ -1134,7 +1137,7 @@ function kern_linkat(fd1,fd2:Integer;path1,path2:PChar;segflg:uio_seg;follow:Int var vp:p_vnode; mp:p_mount; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; lvfslocked:Integer; error:Integer; @@ -1236,7 +1239,7 @@ var vattr:t_vattr; syspath:PChar; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin if (segflg=UIO_SYSSPACE) then @@ -1326,7 +1329,7 @@ var mp:p_mount; vp:p_vnode; error:Integer; - nd:nameidata; + nd:t_nameidata; sb:t_stat; vfslocked:Integer; @@ -1575,7 +1578,7 @@ label out1; var vp:p_vnode; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; error:Integer; begin @@ -1616,7 +1619,7 @@ function kern_statat_vnhook(flag,fd:Integer; sbp:p_stat; hook:t_statat_hook_cb):Integer; var - nd:nameidata; + nd:t_nameidata; sb:t_stat; error, vfslocked:Integer; begin @@ -1656,7 +1659,6 @@ end; function kern_statat(flag,fd:Integer;path:PChar; pathseg:uio_seg;sbp:p_stat):Integer; begin - Exit(kern_statat_vnhook(flag, fd, path, pathseg, sbp, nil)); end; @@ -1712,7 +1714,7 @@ end; function kern_pathconf(path:PChar;pathseg:uio_seg;name:Integer;flags:QWORD):Integer; var td:p_kthread; - nd:nameidata; + nd:t_nameidata; error,vfslocked:Integer; begin td:=curkthread; @@ -1750,7 +1752,7 @@ var aiov:iovec; auio:t_uio; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin if (count > IOSIZE_MAX) then @@ -1859,7 +1861,7 @@ end; function sys_chflags(path:PChar;flags:Integer):Integer; var error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin NDINIT(@nd, LOOKUP, FOLLOW or MPSAFE or AUDITVNODE1, UIO_USERSPACE, path, curkthread); @@ -1880,7 +1882,7 @@ end; function sys_lchflags(path:PChar;flags:Integer):Integer; var error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin NDINIT(@nd, LOOKUP, NOFOLLOW or MPSAFE or AUDITVNODE1, UIO_USERSPACE, path, curkthread); @@ -1944,7 +1946,7 @@ end; function kern_fchmodat(fd:Integer;path:PChar;pathseg:uio_seg;mode,flag:Integer):Integer; var error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; follow:Integer; begin @@ -2043,7 +2045,7 @@ end; function kern_fchownat(fd:Integer;path:PChar;pathseg:uio_seg;uid,gid,flag:Integer):Integer; var - nd:nameidata; + nd:t_nameidata; error,vfslocked,follow:Integer; begin if (flag and AT_SYMLINK_NOFOLLOW)<>0 then @@ -2194,7 +2196,7 @@ end; function kern_utimesat(fd:Integer;path:PChar;pathseg:uio_seg; tptr:ptimeval;tptrseg:uio_seg):Integer; var - nd:nameidata; + nd:t_nameidata; ts:array[0..1] of timespec; error,vfslocked:Integer; begin @@ -2238,7 +2240,7 @@ function kern_lutimes(path:PChar;pathseg:uio_seg; var ts:array[0..1] of timespec; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin error:=getutimes(tptr, tptrseg, ts); @@ -2300,7 +2302,7 @@ var vp:p_vnode; rl_cookie:Pointer; vattr:t_vattr; - nd:nameidata; + nd:t_nameidata; error,vfslocked:Integer; begin if (length < 0) then @@ -2413,7 +2415,7 @@ label var mp:p_mount; tvp,fvp,tdvp:p_vnode; - fromnd,tond:nameidata; + fromnd,tond:t_nameidata; tvfslocked:Integer; fvfslocked:Integer; error:Integer; @@ -2556,7 +2558,7 @@ var vp:p_vnode; vattr:t_vattr; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin restart: @@ -2641,7 +2643,7 @@ var mp:p_mount; vp:p_vnode; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin restart: @@ -2720,7 +2722,7 @@ begin Exit(kern_rmdir(path, UIO_USERSPACE)); end; -function kern_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer; +function kern_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer; label unionread, fail; @@ -2781,9 +2783,9 @@ unionread: VFS_UNLOCK_GIANT(vfslocked); goto fail; end; - if (count=auio.uio_resid and - (vp^.v_vflag and VV_ROOT) and - (p_mount(vp^.v_mount)^.mnt_flag and MNT_UNION)) then + if (count=auio.uio_resid) and + ((vp^.v_vflag and VV_ROOT)<>0) and + ((p_mount(vp^.v_mount)^.mnt_flag and MNT_UNION)<>0) then begin tvp:=vp; vp:=p_mount(vp^.v_mount)^.mnt_vnodecovered; @@ -2808,7 +2810,7 @@ end; { * Read a block of directory entries in a filesystem independent format. } -function sys_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer; +function sys_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer; var base:Int64; error:Integer; @@ -2821,7 +2823,7 @@ begin Exit(error); end; -function sys_getdents(fd:Integer;buf:PChar;count:DWORD):Integer; +function sys_getdents(fd:Integer;buf:Pointer;count:DWORD):Integer; begin Exit(sys_getdirentries(fd,buf,count,nil)); end; @@ -2849,7 +2851,7 @@ var vp:p_vnode; vattr:t_vattr; error:Integer; - nd:nameidata; + nd:t_nameidata; vfslocked:Integer; begin NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF or MPSAFE or AUDITVNODE1, diff --git a/sys/vfs/vfs_vnode.pas b/sys/vfs/vfs_vnode.pas index e5723b2b..2fc28c06 100644 --- a/sys/vfs/vfs_vnode.pas +++ b/sys/vfs/vfs_vnode.pas @@ -275,7 +275,7 @@ function vn_rangelock_rlock(vp:p_vnode;start,__end:Int64):Pointer; function vn_rangelock_wlock(vp:p_vnode;start,__end:Int64):Pointer; var - rootvnode:p_vnode; + rootvnode:p_vnode=nil; implementation diff --git a/sys/vfs/vfs_vnops.pas b/sys/vfs/vfs_vnops.pas index d74a573a..c232bc14 100644 --- a/sys/vfs/vfs_vnops.pas +++ b/sys/vfs/vfs_vnops.pas @@ -61,7 +61,6 @@ const function foffset_get(fp:p_file):Int64; inline; function foffset_lock(fp:p_file;flags:Integer):Int64; -procedure foffset_lock(fp:p_file;val:Int64;flags:Integer); procedure foffset_unlock(fp:p_file;val:Int64;flags:Integer); procedure foffset_lock_uio(fp:p_file;uio:p_uio;flags:Integer); procedure foffset_unlock_uio(fp:p_file;uio:p_uio;flags:Integer); @@ -319,16 +318,19 @@ function vn_start_write_locked(mp:p_mount;flags:Integer):Integer; label unlock; var + td:p_kthread; error:Integer; begin mtx_assert(MNT_MTX(mp)^); error:=0; + td:=curkthread; { * Check on status of suspension. } - if ((curkthread^.td_pflags and TDP_IGNSUSP)=0) or - (mp^.mnt_susp_owner<>curkthread) then + if (td<>nil) then + if ((td^.td_pflags and TDP_IGNSUSP)=0) or + (mp^.mnt_susp_owner<>td) then begin while ((mp^.mnt_kern_flag and MNTK_SUSPEND)<>0) do begin @@ -342,6 +344,7 @@ begin goto unlock; end; end; + if ((flags and V_XSLEEP)<>0) then goto unlock; Inc(mp^.mnt_writeopcount); @@ -495,9 +498,9 @@ begin end; sb^.st_mode:=mode; sb^.st_nlink:=vap^.va_nlink; - sb^.st_uid:=vap^.va_uid; - sb^.st_gid:=vap^.va_gid; - sb^.st_rdev:=vap^.va_rdev; + sb^.st_uid :=vap^.va_uid; + sb^.st_gid :=vap^.va_gid; + sb^.st_rdev :=vap^.va_rdev; if (vap^.va_size > High(Int64)) then Exit(EOVERFLOW); sb^.st_size:=vap^.va_size; @@ -539,37 +542,55 @@ begin end; function foffset_lock(fp:p_file;flags:Integer):Int64; +var + mtxp:p_mtx; begin + Result:=0; Assert((flags and FOF_OFFSET)=0, 'FOF_OFFSET passed'); - if ((flags and FOF_NOLOCK)<>0) then - Exit(fp^.f_offset); -end; + mtxp:=mtx_pool_find(mtxpool_sleep, fp); + mtx_lock(mtxp^); -procedure foffset_lock(fp:p_file;val:Int64;flags:Integer); -begin - Assert((flags and FOF_OFFSET)=0, ('FOF_OFFSET passed')); - - if ((flags and FOF_NOLOCK)<>0) then + if ((flags and FOF_NOLOCK)=0) then begin - if ((flags and FOF_NOUPDATE)=0) then - fp^.f_offset:=val; - if ((flags and FOF_NEXTOFF)<>0) then - fp^.f_nextoff:=val; + while ((fp^.f_vnread_flags and FOFFSET_LOCKED)<>0) do + begin + fp^.f_vnread_flags:=fp^.f_vnread_flags or FOFFSET_LOCK_WAITING; + msleep(@fp^.f_vnread_flags, mtxp, PUSER, 'vofflock', 0); + end; + fp^.f_vnread_flags:=fp^.f_vnread_flags or FOFFSET_LOCKED; end; + Result:=fp^.f_offset; + + mtx_unlock(mtxp^); end; procedure foffset_unlock(fp:p_file;val:Int64;flags:Integer); +var + mtxp:p_mtx; begin - Assert((flags and FOF_OFFSET)=0, ('FOF_OFFSET passed')); + Assert((flags and FOF_OFFSET)=0,'FOF_OFFSET passed'); - if ((flags and FOF_NOLOCK)<>0) then + mtxp:=mtx_pool_find(mtxpool_sleep, fp); + mtx_lock(mtxp^); + + if ((flags and FOF_NOUPDATE)=0) then + fp^.f_offset:=val; + + if ((flags and FOF_NEXTOFF)<>0) then + fp^.f_nextoff:=val; + + if ((flags and FOF_NOLOCK)=0) then begin - if ((flags and FOF_NOUPDATE)=0) then - fp^.f_offset:=val; - if ((flags and FOF_NEXTOFF)<>0) then - fp^.f_nextoff:=val; + Assert((fp^.f_vnread_flags and FOFFSET_LOCKED)<>0,'Lost FOFFSET_LOCKED'); + + if ((fp^.f_vnread_flags and FOFFSET_LOCK_WAITING)<>0) then + wakeup(@fp^.f_vnread_flags); + + fp^.f_vnread_flags:=0; end; + + mtx_unlock(mtxp^); end; procedure foffset_lock_uio(fp:p_file;uio:p_uio;flags:Integer); diff --git a/sys/vfs/vnamei.pas b/sys/vfs/vnamei.pas index 0785c81f..5bddfed8 100644 --- a/sys/vfs/vnamei.pas +++ b/sys/vfs/vnamei.pas @@ -100,45 +100,45 @@ type { * Encapsulation of namei parameters. } - p_nameidata=^nameidata; - nameidata=packed record - { - * Arguments to namei/lookup. - } - ni_dirp:PChar; { pathname pointer } - ni_segflg:uio_seg; { location of pathname } - _align1 :Integer; - ni_rightsneeded:cap_rights_t; { rights required to look up vnode } - { - * Arguments to lookup. - } - ni_startdir:p_vnode; { starting directory } - ni_rootdir :p_vnode; { logical root directory } - ni_topdir :p_vnode; { logical top directory } - ni_dirfd :Integer; { starting directory for *at functions } - ni_strictrelative:Integer; { relative lookup only; no '..' } - { - * Results: returned from namei - } - ni_baserights:cap_rights_t; { rights the *at base has (or -1) } - { - * Results: returned from/manipulated by lookup - } - ni_vp :p_vnode; { vnode of result } - ni_dvp:p_vnode; { vnode of intermediate directory } - { - * Shared between namei and lookup/commit routines. - } - ni_pathlen:QWORD; { remaining chars in path } - ni_next :PChar; { next location in pathname } - ni_loopcnt:QWORD; { count of symlinks encountered } - { - * Lookup parameters: this structure describes the subset of - * information from the nameidata structure that is passed - * through the VOP interface. - } - ni_cnd:componentname; -end; + p_nameidata=^t_nameidata; + t_nameidata=packed record + { + * Arguments to namei/lookup. + } + ni_dirp:PChar; { pathname pointer } + ni_segflg:uio_seg; { location of pathname } + _align1 :Integer; + ni_rightsneeded:cap_rights_t; { rights required to look up vnode } + { + * Arguments to lookup. + } + ni_startdir:p_vnode; { starting directory } + ni_rootdir :p_vnode; { logical root directory } + ni_topdir :p_vnode; { logical top directory } + ni_dirfd :Integer; { starting directory for *at functions } + ni_strictrelative:Integer; { relative lookup only; no '..' } + { + * Results: returned from namei + } + ni_baserights:cap_rights_t; { rights the *at base has (or -1) } + { + * Results: returned from/manipulated by lookup + } + ni_vp :p_vnode; { vnode of result } + ni_dvp:p_vnode; { vnode of intermediate directory } + { + * Shared between namei and lookup/commit routines. + } + ni_pathlen:QWORD; { remaining chars in path } + ni_next :PChar; { next location in pathname } + ni_loopcnt:QWORD; { count of symlinks encountered } + { + * Lookup parameters: this structure describes the subset of + * information from the nameidata structure that is passed + * through the VOP interface. + } + ni_cnd:componentname; + end; function NDHASGIANT(ndp:p_nameidata):Integer; inline;