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;