mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
86bb82ed62
commit
253d683766
|
@ -12,9 +12,11 @@
|
|||
*.prx
|
||||
*.sprx
|
||||
*.dump
|
||||
*.h
|
||||
link.res
|
||||
lib/
|
||||
backup/
|
||||
shader_dump/*
|
||||
avplayer_dump/*
|
||||
savedata/*
|
||||
tools/vop_generator/vnode_if.*
|
||||
|
|
|
@ -6,7 +6,7 @@ unit dead_vnops;
|
|||
interface
|
||||
|
||||
uses
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfs_default,
|
||||
vnode_if;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ uses
|
|||
mqueue,
|
||||
vfile,
|
||||
vdirent,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vmount,
|
||||
time,
|
||||
kern_conf,
|
||||
|
|
|
@ -41,7 +41,7 @@ implementation
|
|||
uses
|
||||
time,
|
||||
vdirent,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
kern_mtx,
|
||||
kern_sx,
|
||||
vfs_vnops,
|
||||
|
@ -145,7 +145,11 @@ begin
|
|||
end;
|
||||
break;
|
||||
end;
|
||||
Assert((de=nil) or ((de^.de_flags and DE_DOOMED)=0),'devfs_find: Exiting a doomed entry');
|
||||
|
||||
if (de<>nil) then
|
||||
begin
|
||||
Assert((de^.de_flags and DE_DOOMED)=0,'devfs_find: Exiting a doomed entry');
|
||||
end;
|
||||
Exit(de);
|
||||
end;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ unit devfs_vfsops;
|
|||
interface
|
||||
|
||||
uses
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vmount,
|
||||
devfs,
|
||||
kern_id;
|
||||
|
@ -41,8 +41,6 @@ const
|
|||
vfs_extattrctl :nil;
|
||||
vfs_sysctl :nil;
|
||||
vfs_susp_clean :nil;
|
||||
vfs_reclaim_lowervp:nil;
|
||||
vfs_unlink_lowervp :nil;
|
||||
);
|
||||
|
||||
var
|
||||
|
|
|
@ -16,7 +16,7 @@ uses
|
|||
vstat,
|
||||
vuio,
|
||||
vfcntl,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vnamei,
|
||||
vnode_if,
|
||||
vfs_default,
|
||||
|
@ -71,7 +71,7 @@ function devfs_stat_f(fp:p_file;sb:p_stat):Integer;
|
|||
function devfs_symlink(ap:p_vop_symlink_args):Integer;
|
||||
function devfs_truncate_f(fp:p_file;length:Int64):Integer;
|
||||
function devfs_write_f(fp:p_file;uio:p_uio;flags:Integer):Integer;
|
||||
function dev2udev(x:p_cdev):DWORD;
|
||||
function dev2udev(x:p_cdev):Integer;
|
||||
|
||||
const
|
||||
devfs_vnodeops:vop_vector=(
|
||||
|
@ -370,6 +370,7 @@ begin
|
|||
sx_xunlock(@dmp^.dm_lock);
|
||||
vn_lock(vp, locked or LK_RETRY);
|
||||
sx_xlock(@dmp^.dm_lock);
|
||||
|
||||
if DEVFS_DMP_DROP(dmp) then
|
||||
begin
|
||||
sx_xunlock(@dmp^.dm_lock);
|
||||
|
@ -640,8 +641,13 @@ loop:
|
|||
Inc(dev^.si_usecount,vp^.v_usecount);
|
||||
{ Special casing of ttys for deadfs. Probably redundant. }
|
||||
dsw:=dev^.si_devsw;
|
||||
if (dsw<>nil) and ((dsw^.d_flags and D_TTY)<>0) then
|
||||
|
||||
if (dsw<>nil) then
|
||||
if ((dsw^.d_flags and D_TTY)<>0) then
|
||||
begin
|
||||
vp^.v_vflag:=vp^.v_vflag or VV_ISTTY;
|
||||
end;
|
||||
|
||||
dev_unlock();
|
||||
VI_UNLOCK(vp);
|
||||
if ((dev^.si_flags and SI_ETERNAL)<>0) then
|
||||
|
@ -739,7 +745,8 @@ begin
|
|||
}
|
||||
oldvp:=nil;
|
||||
//sx_xlock(@proctree_lock);
|
||||
//if (td<>nil) and (vp=td^.td_proc^.p_session^.s_ttyvp) then
|
||||
//if (td<>nil) then
|
||||
//if (vp=td^.td_proc^.p_session^.s_ttyvp) then
|
||||
//begin
|
||||
// SESS_LOCK(td^.td_proc^.p_session);
|
||||
// VI_LOCK(vp);
|
||||
|
@ -1041,6 +1048,8 @@ begin
|
|||
end;
|
||||
|
||||
function devfs_lookupx(ap:p_vop_lookup_args;dm_unlock:PInteger):Integer;
|
||||
label
|
||||
_or;
|
||||
var
|
||||
td:p_kthread;
|
||||
cnp:p_componentname;
|
||||
|
@ -1157,15 +1166,23 @@ begin
|
|||
|
||||
dev_lock();
|
||||
dde:=@cdev2priv(cdev)^.cdp_dirents[dmp^.dm_idx];
|
||||
if (dde<>nil) and (dde^<>nil) then
|
||||
|
||||
if (dde<>nil) then
|
||||
if (dde^<>nil) then
|
||||
begin
|
||||
de:=dde^;
|
||||
end;
|
||||
|
||||
dev_unlock();
|
||||
dev_rel(cdev);
|
||||
break;
|
||||
end;
|
||||
|
||||
if (de=nil) or ((de^.de_flags and DE_WHITEOUT)<>0) then
|
||||
if (de=nil) then goto _or;
|
||||
|
||||
if ((de^.de_flags and DE_WHITEOUT)<>0) then
|
||||
begin
|
||||
_or:
|
||||
if ((nameiop=CREATE) or (nameiop=RENAME)) and
|
||||
((flags and (LOCKPARENT or WANTPARENT))<>0) and
|
||||
((flags and ISLASTCN)<>0) then
|
||||
|
@ -1943,7 +1960,7 @@ begin
|
|||
Exit(error);
|
||||
end;
|
||||
|
||||
function dev2udev(x:p_cdev):DWORD;
|
||||
function dev2udev(x:p_cdev):Integer;
|
||||
begin
|
||||
if (x=nil) then
|
||||
Exit(NODEV);
|
||||
|
|
|
@ -8,8 +8,8 @@ interface
|
|||
uses
|
||||
vmount,
|
||||
vfs_mount,
|
||||
vfs_vnode,
|
||||
fdesc;
|
||||
vnode,
|
||||
fdescfs;
|
||||
|
||||
{
|
||||
* /dev/fd Filesystem
|
||||
|
@ -37,8 +37,6 @@ const
|
|||
vfs_extattrctl :nil;
|
||||
vfs_sysctl :nil;
|
||||
vfs_susp_clean :nil;
|
||||
vfs_reclaim_lowervp:nil;
|
||||
vfs_unlink_lowervp :nil;
|
||||
);
|
||||
|
||||
//VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC);
|
||||
|
|
|
@ -8,10 +8,10 @@ interface
|
|||
uses
|
||||
mqueue,
|
||||
vmount,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfs_default,
|
||||
vnode_if,
|
||||
fdesc;
|
||||
fdescfs;
|
||||
|
||||
{
|
||||
* /dev/fd Filesystem
|
||||
|
@ -156,6 +156,7 @@ end;
|
|||
|
||||
function fdesc_allocvp(ftype:fdntype;fd_fd,ix:Integer;mp:p_mount;vpp:pp_vnode):Integer;
|
||||
label
|
||||
_or,
|
||||
loop;
|
||||
var
|
||||
fmp:p_fdescmount;
|
||||
|
@ -174,7 +175,14 @@ loop:
|
|||
* protected by the hashmtx.
|
||||
}
|
||||
fmp:=p_fdescmount(mp^.mnt_data);
|
||||
if (fmp=nil) or ((fmp^.flags and FMNT_UNMOUNTF)<>0) then
|
||||
|
||||
if (fmp=nil) then
|
||||
begin
|
||||
mtx_unlock(fdesc_hashmtx);
|
||||
Exit(-1);
|
||||
end;
|
||||
|
||||
if ((fmp^.flags and FMNT_UNMOUNTF)<>0) then
|
||||
begin
|
||||
mtx_unlock(fdesc_hashmtx);
|
||||
Exit(-1);
|
||||
|
@ -230,8 +238,12 @@ loop:
|
|||
* protected by the hashmtx.
|
||||
}
|
||||
fmp:=p_fdescmount(mp^.mnt_data);
|
||||
if (fmp=nil) or ((fmp^.flags and FMNT_UNMOUNTF)<>0) then
|
||||
|
||||
if (fmp=nil) then goto _or;
|
||||
|
||||
if ((fmp^.flags and FMNT_UNMOUNTF)<>0) then
|
||||
begin
|
||||
_or:
|
||||
mtx_unlock(fdesc_hashmtx);
|
||||
vgone(vp);
|
||||
vput(vp);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
unit fdesc;
|
||||
unit fdescfs;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
@ -8,7 +8,7 @@ interface
|
|||
uses
|
||||
mqueue,
|
||||
vmount,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
kern_mtx,
|
||||
subr_hash;
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
unit null_subr;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
mqueue,
|
||||
vmount,
|
||||
vnode,
|
||||
nullfs,
|
||||
kern_mtx,
|
||||
subr_hash;
|
||||
|
||||
{
|
||||
* null layer cache:
|
||||
* Each cache entry holds a reference to the lower vnode
|
||||
* along with a pointer to the alias vnode. When an
|
||||
* entry is added the lower vnode is VREF'd. When the
|
||||
* alias is removed the lower vnode is vrele'd.
|
||||
}
|
||||
function nullfs_init(vfsp:p_vfsconf):Integer;
|
||||
function nullfs_uninit(vfsp:p_vfsconf):Integer;
|
||||
|
||||
function null_hashget(mp:p_mount;lowervp:p_vnode):p_vnode;
|
||||
function null_hashins(mp:p_mount;xp:p_null_node):p_vnode;
|
||||
procedure null_destroy_proto(vp:p_vnode;xp:Pointer);
|
||||
procedure null_insmntque_dtr(vp:p_vnode;xp:Pointer);
|
||||
function null_nodeget(mp:p_mount;lowervp:p_vnode;vpp:pp_vnode):Integer;
|
||||
procedure null_hashrem(xp:p_null_node);
|
||||
|
||||
|
||||
type
|
||||
p_null_node_hashhead=^t_null_node_hashhead;
|
||||
t_null_node_hashhead=LIST_HEAD; //null_node
|
||||
|
||||
var
|
||||
null_node_hashtbl:p_null_node_hashhead=nil;
|
||||
null_hash_mask :QWORD=0;
|
||||
null_hashmtx:mtx;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
vfs_subr,
|
||||
vfs_vnops,
|
||||
dead_vnops,
|
||||
vnode_if,
|
||||
null_vnops;
|
||||
|
||||
function vfs_hash_index(vp:p_vnode):DWORD;
|
||||
begin
|
||||
Result:=(vp^.v_hash + p_mount(vp^.v_mount)^.mnt_hashseed);
|
||||
end;
|
||||
|
||||
function NULL_NHASH(vp:p_vnode):Pointer;
|
||||
begin
|
||||
Result:=@null_node_hashtbl[vfs_hash_index(vp) and null_hash_mask];
|
||||
end;
|
||||
|
||||
{
|
||||
* Initialise cache headers
|
||||
}
|
||||
function nullfs_init(vfsp:p_vfsconf):Integer;
|
||||
const
|
||||
desiredvnodes=64;
|
||||
begin
|
||||
null_node_hashtbl:=hashinit(desiredvnodes, @null_hash_mask);
|
||||
mtx_init(null_hashmtx, 'nullhs');
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function nullfs_uninit(vfsp:p_vfsconf):Integer;
|
||||
begin
|
||||
mtx_destroy(null_hashmtx);
|
||||
hashdestroy(null_node_hashtbl, null_hash_mask);
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Exita VREF'ed alias for lower vnode if already exists, else 0.
|
||||
* Lower vnode should be locked on entry and will be left locked on exit.
|
||||
}
|
||||
function null_hashget(mp:p_mount;lowervp:p_vnode):p_vnode;
|
||||
var
|
||||
hd:Pointer;
|
||||
a:p_null_node;
|
||||
vp:p_vnode;
|
||||
begin
|
||||
ASSERT_VOP_LOCKED(lowervp, 'nil_hashget');
|
||||
|
||||
{
|
||||
* Find hash base, and then search the (two-way) linked
|
||||
* list looking for a nil_node structure which is referencing
|
||||
* the lower vnode. If found, the increment the nil_node
|
||||
* reference count (but NOT the lower vnode's VREF counter).
|
||||
}
|
||||
hd:=NULL_NHASH(lowervp);
|
||||
mtx_lock(null_hashmtx);
|
||||
|
||||
a:=LIST_FIRST(hd);
|
||||
while (a<>nil) do
|
||||
begin
|
||||
if (a^.null_lowervp=lowervp) and (NULLTOV(a)^.v_mount=mp) then
|
||||
begin
|
||||
{
|
||||
* Since we have the lower node locked the nilfs
|
||||
* node can not be in the process of recycling. If
|
||||
* it had been recycled before we grabed the lower
|
||||
* lock it would not have been found on the hash.
|
||||
}
|
||||
vp:=NULLTOV(a);
|
||||
vref(vp);
|
||||
mtx_unlock(null_hashmtx);
|
||||
Exit(vp);
|
||||
end;
|
||||
a:=LIST_NEXT(a,@a^.null_hash);
|
||||
end;
|
||||
mtx_unlock(null_hashmtx);
|
||||
Exit(nil);
|
||||
end;
|
||||
|
||||
{
|
||||
* Act like nil_hashget, but add passed null_node to hash if no existing
|
||||
* node found.
|
||||
}
|
||||
function null_hashins(mp:p_mount;xp:p_null_node):p_vnode;
|
||||
var
|
||||
hd:Pointer;
|
||||
oxp:p_null_node;
|
||||
ovp:p_vnode;
|
||||
begin
|
||||
hd:=NULL_NHASH(xp^.null_lowervp);
|
||||
mtx_lock(null_hashmtx);
|
||||
oxp:=LIST_FIRST(hd);
|
||||
while (oxp<>nil) do
|
||||
begin
|
||||
if (oxp^.null_lowervp=xp^.null_lowervp) and
|
||||
(NULLTOV(oxp)^.v_mount=mp) then
|
||||
begin
|
||||
{
|
||||
* See nil_hashget for a description of this
|
||||
* operation.
|
||||
}
|
||||
ovp:=NULLTOV(oxp);
|
||||
vref(ovp);
|
||||
mtx_unlock(null_hashmtx);
|
||||
Exit(ovp);
|
||||
end;
|
||||
oxp:=LIST_NEXT(oxp,@oxp^.null_hash);
|
||||
end;
|
||||
LIST_INSERT_HEAD(hd, xp,@xp^.null_hash);
|
||||
mtx_unlock(null_hashmtx);
|
||||
Exit(nil);
|
||||
end;
|
||||
|
||||
procedure null_destroy_proto(vp:p_vnode;xp:Pointer);
|
||||
begin
|
||||
mtx_lock(vp^.v_lock);
|
||||
//lockmgr(@vp^.v_lock, LK_EXCLUSIVE, nil);
|
||||
VI_LOCK(vp);
|
||||
vp^.v_data :=nil;
|
||||
vp^.v_vnlock:=@vp^.v_lock;
|
||||
vp^.v_op :=@dead_vnodeops;
|
||||
VI_UNLOCK(vp);
|
||||
vgone(vp);
|
||||
vput(vp);
|
||||
|
||||
FreeMem(xp);
|
||||
end;
|
||||
|
||||
procedure null_insmntque_dtr(vp:p_vnode;xp:Pointer);
|
||||
begin
|
||||
vput(p_null_node(xp)^.null_lowervp);
|
||||
null_destroy_proto(vp, xp);
|
||||
end;
|
||||
|
||||
{
|
||||
* Make a new or get existing nilfs node.
|
||||
* Vp is the alias vnode, lowervp is the lower vnode.
|
||||
*
|
||||
* The lowervp assumed to be locked and having 'spare' reference. This routine
|
||||
* vrele lowervp if nilfs node was taken from hash. Otherwise it 'transfers'
|
||||
* the caller's 'spare' reference to created nilfs vnode.
|
||||
}
|
||||
function null_nodeget(mp:p_mount;lowervp:p_vnode;vpp:pp_vnode):Integer;
|
||||
var
|
||||
xp:p_null_node;
|
||||
vp:p_vnode;
|
||||
error:Integer;
|
||||
begin
|
||||
ASSERT_VOP_LOCKED(lowervp, 'lowervp');
|
||||
Assert(lowervp^.v_usecount >= 1,'Unreferenced vnode %p');
|
||||
|
||||
{ Lookup the hash firstly. }
|
||||
vpp^:=null_hashget(mp, lowervp);
|
||||
if (vpp^<>nil) then
|
||||
begin
|
||||
vrele(lowervp);
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* The insmntque1() call below requires the exclusive lock on
|
||||
* the nilfs vnode. Upgrade the lock now if hash failed to
|
||||
* provide ready to use vnode.
|
||||
}
|
||||
if (VOP_ISLOCKED(lowervp)<>LK_EXCLUSIVE) then
|
||||
begin
|
||||
Assert((MOUNTTONULLMOUNT(mp)^.nullm_flags and NULLM_CACHE)<>0,'lowervp %p is not excl locked and cache is disabled');
|
||||
vn_lock(lowervp, LK_UPGRADE or LK_RETRY);
|
||||
if ((lowervp^.v_iflag and VI_DOOMED)<>0) then
|
||||
begin
|
||||
vput(lowervp);
|
||||
Exit(ENOENT);
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
* We do not serialize vnode creation, instead we will check for
|
||||
* duplicates later, when adding new vnode to hash.
|
||||
* Note that duplicate can only appear in hash if the lowervp is
|
||||
* locked LK_SHARED.
|
||||
*
|
||||
* Do the MALLOC before the getnewvnode since doing so afterward
|
||||
* might cause a bogus v_data pointer to get dereferenced
|
||||
* elsewhere if MALLOC should block.
|
||||
}
|
||||
xp:=AllocMem(sizeof(t_null_node));
|
||||
|
||||
error:=getnewvnode('nil', mp, @null_vnodeops, @vp);
|
||||
if (error<>0) then
|
||||
begin
|
||||
vput(lowervp);
|
||||
FreeMem(xp);
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
xp^.null_vnode :=vp;
|
||||
xp^.null_lowervp:=lowervp;
|
||||
xp^.null_flags :=0;
|
||||
|
||||
vp^.v_type :=lowervp^.v_type;
|
||||
vp^.v_data :=xp;
|
||||
vp^.v_vnlock:=lowervp^.v_vnlock;
|
||||
|
||||
error:=insmntque1(vp, mp, @null_insmntque_dtr, xp);
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
{
|
||||
* Atomically insert our new node into the hash or vget existing
|
||||
* if someone else has beaten us to it.
|
||||
}
|
||||
vpp^:=null_hashins(mp, xp);
|
||||
if (vpp^<>nil) then
|
||||
begin
|
||||
vrele(lowervp);
|
||||
null_destroy_proto(vp, xp);
|
||||
Exit(0);
|
||||
end;
|
||||
vpp^:=vp;
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Remove node from hash.
|
||||
}
|
||||
procedure null_hashrem(xp:p_null_node);
|
||||
begin
|
||||
mtx_lock(null_hashmtx);
|
||||
LIST_REMOVE(xp,@xp^.null_hash);
|
||||
mtx_unlock(null_hashmtx);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,350 @@
|
|||
unit null_vfsops;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
mqueue,
|
||||
vnode,
|
||||
vmount,
|
||||
nullfs,
|
||||
null_subr;
|
||||
|
||||
function nullfs_mount(mp:p_mount):Integer;
|
||||
function nullfs_unmount(mp:p_mount;mntflags:Integer):Integer;
|
||||
function nullfs_root(mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
|
||||
function nullfs_quotactl(mp:p_mount;cmd,uid:Integer;arg:Pointer):Integer;
|
||||
function nullfs_statfs(mp:p_mount;sbp:p_statfs):Integer;
|
||||
function nullfs_sync(mp:p_mount;waitfor:Integer):Integer;
|
||||
function nullfs_vget(mp:p_mount;ino:DWORD;flags:Integer;vpp:pp_vnode):Integer;
|
||||
function nullfs_fhtovp(mp:p_mount;fidp:p_fid;flags:Integer;vpp:pp_vnode):Integer;
|
||||
function nullfs_extattrctl(mp:p_mount;cmd:Integer;filename_vp:p_vnode;namespace:Integer;attrname:PChar):Integer;
|
||||
|
||||
const
|
||||
_null_vfsops:vfsops=(
|
||||
vfs_mount :@nullfs_mount;
|
||||
vfs_cmount :nil;
|
||||
vfs_unmount :@nullfs_unmount;
|
||||
vfs_root :@nullfs_root;
|
||||
vfs_quotactl :@nullfs_quotactl;
|
||||
vfs_statfs :@nullfs_statfs;
|
||||
vfs_sync :@nullfs_sync;
|
||||
vfs_vget :@nullfs_vget;
|
||||
vfs_fhtovp :@nullfs_fhtovp;
|
||||
vfs_checkexp :nil;
|
||||
vfs_init :@nullfs_init;
|
||||
vfs_uninit :@nullfs_uninit;
|
||||
vfs_extattrctl :@nullfs_extattrctl;
|
||||
vfs_sysctl :nil;
|
||||
vfs_susp_clean :nil;
|
||||
);
|
||||
|
||||
//VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK or VFCF_JAIL);
|
||||
nullfs_vfsconf:vfsconf=(
|
||||
vfc_version :VFS_VERSION;
|
||||
vfc_name :'nullfs';
|
||||
vfc_vfsops :@_null_vfsops;
|
||||
vfc_typenum :-1;
|
||||
vfc_refcount:0;
|
||||
vfc_flags :VFCF_LOOPBACK or VFCF_JAIL;
|
||||
vfc_opts :nil;
|
||||
vfc_list :(tqe_next:nil;tqe_prev:nil)
|
||||
);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
vuio,
|
||||
vnamei,
|
||||
vfs_mount,
|
||||
vfs_lookup,
|
||||
vfs_vnops,
|
||||
vfs_subr,
|
||||
vnode_if,
|
||||
null_vnops,
|
||||
kern_thr,
|
||||
kern_mtx,
|
||||
kern_synch;
|
||||
|
||||
{
|
||||
* Mount null layer
|
||||
}
|
||||
function nullfs_mount(mp:p_mount):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
lowerrootvp,vp,nullm_rootvp:p_vnode;
|
||||
xmp:p_null_mount;
|
||||
target:PChar;
|
||||
isvnunlocked,len:Integer;
|
||||
nd:t_nameidata;
|
||||
ndp:p_nameidata;
|
||||
begin
|
||||
error:=0;
|
||||
isvnunlocked:=0;
|
||||
ndp:=@nd;
|
||||
|
||||
//if (prison_allow(td^.td_ucred, PR_ALLOW_MOUNT_NULLFS)=0) then
|
||||
// Exit(EPERM);
|
||||
|
||||
//if ((mp^.mnt_flag and MNT_ROOTFS)<>0) then
|
||||
// Exit(EOPNOTSUPP);
|
||||
|
||||
{
|
||||
* Update is a no-op
|
||||
}
|
||||
if ((mp^.mnt_flag and MNT_UPDATE)<>0) then
|
||||
begin
|
||||
{
|
||||
* Only support update mounts for NFS export.
|
||||
}
|
||||
if (vfs_flagopt(mp^.mnt_optnew, 'export', nil, 0)<>0) then
|
||||
Exit(0)
|
||||
else
|
||||
Exit(EOPNOTSUPP);
|
||||
end;
|
||||
|
||||
{
|
||||
* Get argument
|
||||
}
|
||||
error:=vfs_getopt(mp^.mnt_optnew, {'target'} 'fspath', @target, @len);
|
||||
if (error<>0) or (target[len - 1]<>#0) then
|
||||
Exit(EINVAL);
|
||||
|
||||
{
|
||||
* Unlock lower node to avoid possible deadlock.
|
||||
}
|
||||
if (mp^.mnt_vnodecovered^.v_op=@null_vnodeops) and
|
||||
(VOP_ISLOCKED(mp^.mnt_vnodecovered)=LK_EXCLUSIVE) then
|
||||
begin
|
||||
VOP_UNLOCK(mp^.mnt_vnodecovered, 0);
|
||||
isvnunlocked:=1;
|
||||
end;
|
||||
{
|
||||
* Find lower node
|
||||
}
|
||||
NDINIT(ndp, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, target, curkthread);
|
||||
error:=nd_namei(ndp);
|
||||
|
||||
{
|
||||
* Re-lock vnode.
|
||||
* XXXKIB This is deadlock-prone as well.
|
||||
}
|
||||
if (isvnunlocked<>0) then
|
||||
vn_lock(mp^.mnt_vnodecovered, LK_EXCLUSIVE or LK_RETRY);
|
||||
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
NDFREE(ndp, NDF_ONLY_PNBUF);
|
||||
|
||||
{
|
||||
* Sanity check on lower vnode
|
||||
}
|
||||
lowerrootvp:=ndp^.ni_vp;
|
||||
|
||||
{
|
||||
* Check multi null mount to avoid `lock against myself' panic.
|
||||
}
|
||||
if (lowerrootvp=VTONULL(mp^.mnt_vnodecovered)^.null_lowervp) then
|
||||
begin
|
||||
vput(lowerrootvp);
|
||||
Exit(EDEADLK);
|
||||
end;
|
||||
|
||||
xmp:=AllocMem(sizeof(t_null_mount));
|
||||
|
||||
{
|
||||
* Save reference to underlying FS
|
||||
}
|
||||
xmp^.nullm_vfs:=lowerrootvp^.v_mount;
|
||||
|
||||
{
|
||||
* Save reference. Each mount also holds
|
||||
* a reference on the root vnode.
|
||||
}
|
||||
error:=null_nodeget(mp, lowerrootvp, @vp);
|
||||
{
|
||||
* Make sure the node alias worked
|
||||
}
|
||||
if (error<>0) then
|
||||
begin
|
||||
FreeMem(xmp);
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
{
|
||||
* Keep a held reference to the root vnode.
|
||||
* It is vrele'd in nullfs_unmount.
|
||||
}
|
||||
nullm_rootvp:=vp;
|
||||
nullm_rootvp^.v_vflag:=nullm_rootvp^.v_vflag or VV_ROOT;
|
||||
xmp^.nullm_rootvp:=nullm_rootvp;
|
||||
|
||||
{
|
||||
* Unlock the node (either the lower or the alias)
|
||||
}
|
||||
VOP_UNLOCK(vp, 0);
|
||||
|
||||
if ((p_mount(NULLVPTOLOWERVP(nullm_rootvp)^.v_mount)^.mnt_flag and MNT_LOCAL)<>0) then
|
||||
begin
|
||||
MNT_ILOCK(mp);
|
||||
mp^.mnt_flag:=mp^.mnt_flag or MNT_LOCAL;
|
||||
MNT_IUNLOCK(mp);
|
||||
end;
|
||||
|
||||
xmp^.nullm_flags:=xmp^.nullm_flags or NULLM_CACHE;
|
||||
|
||||
if (vfs_getopt(mp^.mnt_optnew, 'nocache', nil, nil)=0) then
|
||||
xmp^.nullm_flags:=xmp^.nullm_flags and (not NULLM_CACHE);
|
||||
|
||||
MNT_ILOCK(mp);
|
||||
if ((xmp^.nullm_flags and NULLM_CACHE)<>0) then
|
||||
begin
|
||||
mp^.mnt_kern_flag:=mp^.mnt_kern_flag or
|
||||
(p_mount(lowerrootvp^.v_mount)^.mnt_kern_flag and (MNTK_MPSAFE or MNTK_SHARED_WRITES or MNTK_LOOKUP_SHARED or MNTK_EXTENDED_SHARED));
|
||||
end;
|
||||
mp^.mnt_kern_flag:=mp^.mnt_kern_flag or MNTK_LOOKUP_EXCL_DOTDOT;
|
||||
MNT_IUNLOCK(mp);
|
||||
mp^.mnt_data:= xmp;
|
||||
vfs_getnewfsid(mp);
|
||||
if ((xmp^.nullm_flags and NULLM_CACHE)<>0) then
|
||||
begin
|
||||
MNT_ILOCK(xmp^.nullm_vfs);
|
||||
TAILQ_INSERT_TAIL(@xmp^.nullm_vfs^.mnt_uppers,mp,@mp^.mnt_upper_link);
|
||||
MNT_IUNLOCK(xmp^.nullm_vfs);
|
||||
end;
|
||||
|
||||
vfs_mountedfrom(mp, target);
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Free reference to null layer
|
||||
}
|
||||
function nullfs_unmount(mp:p_mount;mntflags:Integer):Integer;
|
||||
var
|
||||
mntdata:p_null_mount;
|
||||
ump:p_mount;
|
||||
error,flags:Integer;
|
||||
begin
|
||||
if ((mntflags and MNT_FORCE)<>0) then
|
||||
flags:=FORCECLOSE
|
||||
else
|
||||
flags:=0;
|
||||
|
||||
{ There is 1 extra root vnode reference (nullm_rootvp). }
|
||||
error:=vflush(mp, 1, flags);
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
{
|
||||
* Finally, throw away the null_mount structure
|
||||
}
|
||||
mntdata:=mp^.mnt_data;
|
||||
ump:=mntdata^.nullm_vfs;
|
||||
if ((mntdata^.nullm_flags and NULLM_CACHE)<>0) then
|
||||
begin
|
||||
MNT_ILOCK(ump);
|
||||
while ((ump^.mnt_kern_flag and MNTK_VGONE_UPPER)<>0) do
|
||||
begin
|
||||
ump^.mnt_kern_flag:=ump^.mnt_kern_flag or MNTK_VGONE_WAITER;
|
||||
msleep(@ump^.mnt_uppers, @ump^.mnt_mtx, 0, 'vgnupw', 0);
|
||||
end;
|
||||
TAILQ_REMOVE(@ump^.mnt_uppers,mp,@mp^.mnt_upper_link);
|
||||
MNT_IUNLOCK(ump);
|
||||
end;
|
||||
mp^.mnt_data:=nil;
|
||||
|
||||
FreeMem(mntdata);
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function nullfs_root(mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
begin
|
||||
{
|
||||
* Exitlocked reference to root.
|
||||
}
|
||||
vp:=MOUNTTONULLMOUNT(mp)^.nullm_rootvp;
|
||||
VREF(vp);
|
||||
|
||||
//ASSERT_VOP_UNLOCKED(vp, 'root vnode is locked');
|
||||
vn_lock(vp, flags or LK_RETRY);
|
||||
vpp^:=vp;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function nullfs_quotactl(mp:p_mount;cmd,uid:Integer;arg:Pointer):Integer;
|
||||
begin
|
||||
Exit(VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)^.nullm_vfs, cmd, uid, arg));
|
||||
end;
|
||||
|
||||
function nullfs_statfs(mp:p_mount;sbp:p_statfs):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
mstat:t_statfs;
|
||||
begin
|
||||
FillChar(mstat,sizeof(mstat),0);
|
||||
|
||||
error:=VFS_STATFS(MOUNTTONULLMOUNT(mp)^.nullm_vfs, @mstat);
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
{ now copy across the 'interesting' information and fake the rest }
|
||||
sbp^.f_type :=mstat.f_type;
|
||||
sbp^.f_flags :=mstat.f_flags;
|
||||
sbp^.f_bsize :=mstat.f_bsize;
|
||||
sbp^.f_iosize:=mstat.f_iosize;
|
||||
sbp^.f_blocks:=mstat.f_blocks;
|
||||
sbp^.f_bfree :=mstat.f_bfree;
|
||||
sbp^.f_bavail:=mstat.f_bavail;
|
||||
sbp^.f_files :=mstat.f_files;
|
||||
sbp^.f_ffree :=mstat.f_ffree;
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function nullfs_sync(mp:p_mount;waitfor:Integer):Integer;
|
||||
begin
|
||||
{
|
||||
* XXX - Assumes no data cached at null layer.
|
||||
}
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function nullfs_vget(mp:p_mount;ino:DWORD;flags:Integer;vpp:pp_vnode):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
begin
|
||||
Assert((flags and LK_TYPE_MASK)<>0,
|
||||
('nullfs_vget: no lock requested'));
|
||||
|
||||
error:=VFS_VGET(MOUNTTONULLMOUNT(mp)^.nullm_vfs, ino, flags, vpp);
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
Exit(null_nodeget(mp, vpp^, vpp));
|
||||
end;
|
||||
|
||||
function nullfs_fhtovp(mp:p_mount;fidp:p_fid;flags:Integer;vpp:pp_vnode):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
begin
|
||||
error:=VFS_FHTOVP(MOUNTTONULLMOUNT(mp)^.nullm_vfs, fidp, flags, vpp);
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
Exit(null_nodeget(mp, vpp^, vpp));
|
||||
end;
|
||||
|
||||
function nullfs_extattrctl(mp:p_mount;cmd:Integer;filename_vp:p_vnode;namespace:Integer;attrname:PChar):Integer;
|
||||
begin
|
||||
Exit(VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)^.nullm_vfs, cmd, filename_vp, namespace, attrname));
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,888 @@
|
|||
unit null_vnops;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
vnode,
|
||||
vnode_if,
|
||||
vfs_default;
|
||||
|
||||
function null_bypass(ap:p_vop_generic_args):Integer;
|
||||
function null_add_writecount(ap:p_vop_add_writecount_args):Integer;
|
||||
function null_lookup(ap:p_vop_lookup_args):Integer;
|
||||
function null_open(ap:p_vop_open_args):Integer;
|
||||
function null_setattr(ap:p_vop_setattr_args):Integer;
|
||||
function null_getattr(ap:p_vop_getattr_args):Integer;
|
||||
function null_access(ap:p_vop_access_args):Integer;
|
||||
function null_accessx(ap:p_vop_accessx_args):Integer;
|
||||
function null_remove(ap:p_vop_remove_args):Integer;
|
||||
function null_rename(ap:p_vop_rename_args):Integer;
|
||||
function null_rmdir(ap:p_vop_rmdir_args):Integer;
|
||||
function null_lock(ap:p_vop_lock1_args):Integer;
|
||||
function null_unlock(ap:p_vop_unlock_args):Integer;
|
||||
function null_inactive(ap:p_vop_inactive_args):Integer;
|
||||
function null_reclaim(ap:p_vop_reclaim_args):Integer;
|
||||
function null_print(ap:p_vop_print_args):Integer;
|
||||
function null_getwritemount(ap:p_vop_getwritemount_args):Integer;
|
||||
function null_vptofh(ap:p_vop_vptofh_args):Integer;
|
||||
function null_vptocnp(ap:p_vop_vptocnp_args):Integer;
|
||||
function null_link(ap:p_vop_link_args):Integer;
|
||||
|
||||
const
|
||||
null_vnodeops:vop_vector=(
|
||||
vop_default :nil;
|
||||
vop_bypass :@null_bypass;
|
||||
|
||||
vop_islocked :@vop_stdislocked;
|
||||
vop_lookup :@null_lookup;
|
||||
vop_cachedlookup :nil;
|
||||
vop_create :nil;
|
||||
vop_whiteout :nil;
|
||||
vop_mknod :nil;
|
||||
vop_open :@null_open;
|
||||
vop_close :nil;
|
||||
vop_access :@null_access;
|
||||
vop_accessx :@null_accessx;
|
||||
vop_getattr :@null_getattr;
|
||||
vop_setattr :@null_setattr;
|
||||
vop_markatime :nil;
|
||||
vop_read :nil;
|
||||
vop_write :nil;
|
||||
vop_ioctl :nil;
|
||||
vop_poll :nil;
|
||||
vop_kqfilter :nil;
|
||||
vop_revoke :nil;
|
||||
vop_fsync :nil;
|
||||
vop_remove :@null_remove;
|
||||
vop_link :@null_link;
|
||||
vop_rename :@null_rename;
|
||||
vop_mkdir :nil;
|
||||
vop_rmdir :@null_rmdir;
|
||||
vop_symlink :nil;
|
||||
vop_readdir :nil;
|
||||
vop_readlink :nil;
|
||||
vop_inactive :@null_inactive;
|
||||
vop_reclaim :@null_reclaim;
|
||||
vop_lock1 :@null_lock;
|
||||
vop_unlock :@null_unlock;
|
||||
vop_bmap :@VOP_EOPNOTSUPP;
|
||||
vop_strategy :@VOP_EOPNOTSUPP;
|
||||
vop_getwritemount :@null_getwritemount;
|
||||
vop_print :@null_print;
|
||||
vop_pathconf :nil;
|
||||
vop_advlock :nil;
|
||||
vop_advlockasync :nil;
|
||||
vop_advlockpurge :@vop_stdadvlockpurge;
|
||||
vop_reallocblks :nil;
|
||||
vop_getpages :nil;
|
||||
vop_putpages :nil;
|
||||
vop_getacl :nil;
|
||||
vop_setacl :nil;
|
||||
vop_aclcheck :nil;
|
||||
vop_closeextattr :nil;
|
||||
vop_getextattr :nil;
|
||||
vop_listextattr :nil;
|
||||
vop_openextattr :nil;
|
||||
vop_deleteextattr :nil;
|
||||
vop_setextattr :nil;
|
||||
vop_setlabel :nil;
|
||||
vop_vptofh :@null_vptofh;
|
||||
vop_vptocnp :@null_vptocnp;
|
||||
vop_allocate :nil;
|
||||
vop_advise :nil;
|
||||
vop_unp_bind :nil;
|
||||
vop_unp_connect :nil;
|
||||
vop_unp_detach :nil;
|
||||
vop_is_text :nil;
|
||||
vop_set_text :nil;
|
||||
vop_unset_text :nil;
|
||||
vop_get_writecount:nil;
|
||||
vop_add_writecount:@null_add_writecount;
|
||||
);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
nullfs,
|
||||
null_subr,
|
||||
errno,
|
||||
vnamei,
|
||||
vmount,
|
||||
vfs_subr,
|
||||
vfs_vnops,
|
||||
kern_mtx;
|
||||
|
||||
type
|
||||
ppp_vnode=^pp_vnode;
|
||||
|
||||
function null_bypass(ap:p_vop_generic_args):Integer;
|
||||
label
|
||||
_out,
|
||||
_nxt,
|
||||
_err;
|
||||
var
|
||||
this_vp_p:pp_vnode;
|
||||
error:Integer;
|
||||
old_vps:array[0..VDESC_MAX_VPS-1] of p_vnode;
|
||||
vps_p :array[0..VDESC_MAX_VPS-1] of pp_vnode;
|
||||
vppp:ppp_vnode;
|
||||
descp:p_vnodeop_desc;
|
||||
reles,i:Integer;
|
||||
begin
|
||||
descp:=ap^.a_desc;
|
||||
|
||||
{
|
||||
* Map the vnodes going in.
|
||||
* Later, we'll invoke the operation based on
|
||||
* the first mapped vnode's operation vector.
|
||||
}
|
||||
reles:=descp^.vdesc_flags;
|
||||
i:=0;
|
||||
while (i < VDESC_MAX_VPS) do
|
||||
begin
|
||||
if (descp^.vdesc_vp_offsets[i]=Byte(-1)) then
|
||||
break; { bail out at end of list }
|
||||
|
||||
this_vp_p:=VOPARG_OFFSETTO(descp^.vdesc_vp_offsets[i],ap);
|
||||
vps_p[i]:=this_vp_p;
|
||||
{
|
||||
* We're not guaranteed that any but the first vnode
|
||||
* are of our type. Check for and don't map any
|
||||
* that aren't. (We must always map first vp or vclean fails.)
|
||||
}
|
||||
if (i<>0) then
|
||||
begin
|
||||
if (this_vp_p^=nil) then
|
||||
begin
|
||||
old_vps[i]:=nil;
|
||||
goto _nxt;
|
||||
end;
|
||||
if (this_vp_p^^.v_op<>@null_vnodeops) then
|
||||
begin
|
||||
old_vps[i]:=nil;
|
||||
goto _nxt;
|
||||
end;
|
||||
end;
|
||||
|
||||
old_vps[i]:=this_vp_p^;
|
||||
vps_p[i]^:=NULLVPTOLOWERVP(this_vp_p^);
|
||||
{
|
||||
* XXX - Several operations have the side effect
|
||||
* of vrele'ing their vp's. We must account for
|
||||
* that. (This should go away in the future.)
|
||||
}
|
||||
if ((reles and VDESC_VP0_WILLRELE)<>0) then
|
||||
VREF(this_vp_p^);
|
||||
|
||||
//
|
||||
_nxt:
|
||||
reles:=reles shr 1;
|
||||
Inc(i);
|
||||
end;
|
||||
|
||||
{
|
||||
* Call the operation on the lower layer
|
||||
* with the modified argument structure.
|
||||
}
|
||||
if (vps_p[0]=nil) then goto _err;
|
||||
|
||||
if (vps_p[0]^<>nil) then
|
||||
begin
|
||||
error:=VCALL(ap);
|
||||
end else
|
||||
begin
|
||||
_err:
|
||||
Writeln(Format('null_bypass: no map for %s',[descp^.vdesc_name]));
|
||||
error:=EINVAL;
|
||||
end;
|
||||
|
||||
{
|
||||
* Maintain the illusion of call-by-value
|
||||
* by restoring vnodes in the argument structure
|
||||
* to their original value.
|
||||
}
|
||||
reles:=descp^.vdesc_flags;
|
||||
i:=0;
|
||||
while (i < VDESC_MAX_VPS) do
|
||||
begin
|
||||
if (descp^.vdesc_vp_offsets[i]=Byte(-1)) then
|
||||
break; { bail out at end of list }
|
||||
if (old_vps[i]<>nil) then
|
||||
begin
|
||||
vps_p[i]^:=old_vps[i];
|
||||
if ((reles and VDESC_VP0_WILLRELE)<>0) then
|
||||
vrele((vps_p[i])^);
|
||||
end;
|
||||
//
|
||||
reles:=reles shr 1;
|
||||
Inc(i);
|
||||
end;
|
||||
|
||||
{
|
||||
* Map the possible out-going vpp
|
||||
* (Assumes that the lower layer always Exits
|
||||
* a VREF'ed vpp unless it gets an error.)
|
||||
}
|
||||
if (descp^.vdesc_vpp_offset<>VDESC_NO_OFFSET) and
|
||||
((descp^.vdesc_flags and VDESC_NOMAP_VPP)=0) and
|
||||
(error=0) then
|
||||
begin
|
||||
{
|
||||
* XXX - even though some ops have vpp Exited vp's,
|
||||
* several ops actually vrele this before Exiting.
|
||||
* We must avoid these ops.
|
||||
* (This should go away when these ops are regularized.)
|
||||
}
|
||||
if ((descp^.vdesc_flags and VDESC_VPP_WILLRELE)<>0) then
|
||||
goto _out;
|
||||
|
||||
vppp:=VOPARG_OFFSETTO(descp^.vdesc_vpp_offset,ap);
|
||||
|
||||
if (vppp^<>nil) then
|
||||
error:=null_nodeget(old_vps[0]^.v_mount,vppp^^,vppp^);
|
||||
end;
|
||||
|
||||
_out:
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
function null_add_writecount(ap:p_vop_add_writecount_args):Integer;
|
||||
var
|
||||
lvp,vp:p_vnode;
|
||||
error:Integer;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
Assert(vp^.v_writecount + ap^.a_inc >= 0,'wrong writecount inc');
|
||||
if (vp^.v_writecount > 0) and (vp^.v_writecount + ap^.a_inc=0) then
|
||||
error:=VOP_ADD_WRITECOUNT(lvp, -1)
|
||||
else
|
||||
if (vp^.v_writecount=0) and (vp^.v_writecount + ap^.a_inc > 0) then
|
||||
error:=VOP_ADD_WRITECOUNT(lvp, 1)
|
||||
else
|
||||
error:=0;
|
||||
if (error=0) then
|
||||
Inc(vp^.v_writecount,ap^.a_inc);
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
{
|
||||
* We have to carry on the locking protocol on the null layer vnodes
|
||||
* as we progress through the tree. We also have to enforce read-only
|
||||
* if this layer is mounted read-only.
|
||||
}
|
||||
function null_lookup(ap:p_vop_lookup_args):Integer;
|
||||
var
|
||||
cnp:p_componentname;
|
||||
dvp:p_vnode;
|
||||
flags:Integer;
|
||||
vp,ldvp,lvp:p_vnode;
|
||||
error:Integer;
|
||||
begin
|
||||
cnp:=ap^.a_cnp;
|
||||
dvp:=ap^.a_dvp;
|
||||
flags:=cnp^.cn_flags;
|
||||
|
||||
if ((flags and ISLASTCN)<>0) and
|
||||
((p_mount(dvp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) and
|
||||
((cnp^.cn_nameiop=DELETE) or (cnp^.cn_nameiop=RENAME)) then
|
||||
Exit(EROFS);
|
||||
{
|
||||
* Although it is possible to call null_bypass(), we'll do
|
||||
* a direct call to reduce overhead
|
||||
}
|
||||
ldvp:=NULLVPTOLOWERVP(dvp);
|
||||
vp:=nil;
|
||||
lvp:=nil;
|
||||
error:=VOP_LOOKUP(ldvp, @lvp, cnp);
|
||||
|
||||
if (error=EJUSTRETURN) and
|
||||
((flags and ISLASTCN)<>0) and
|
||||
((p_mount(dvp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) and
|
||||
((cnp^.cn_nameiop=CREATE) or (cnp^.cn_nameiop=RENAME)) then
|
||||
error:=EROFS;
|
||||
|
||||
if ((error=0) or (error=EJUSTRETURN)) and (lvp<>nil) then
|
||||
begin
|
||||
if (ldvp=lvp) then
|
||||
begin
|
||||
ap^.a_vpp^:=dvp;
|
||||
VREF(dvp);
|
||||
vrele(lvp);
|
||||
end else
|
||||
begin
|
||||
error:=null_nodeget(dvp^.v_mount, lvp, @vp);
|
||||
if (error=0) then
|
||||
ap^.a_vpp^:=vp;
|
||||
end;
|
||||
end;
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
function null_open(ap:p_vop_open_args):Integer;
|
||||
var
|
||||
retval:Integer;
|
||||
vp,ldvp:p_vnode;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
ldvp:=NULLVPTOLOWERVP(vp);
|
||||
retval:=null_bypass(Pointer(ap));
|
||||
//if (retval=0) then
|
||||
// vp^.v_object:=ldvp^.v_object;
|
||||
Exit(retval);
|
||||
end;
|
||||
|
||||
{
|
||||
* Setattr call. Disallow write attempts if the layer is mounted read-only.
|
||||
}
|
||||
function null_setattr(ap:p_vop_setattr_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
vap:p_vattr;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
vap:=ap^.a_vap;
|
||||
|
||||
if ((vap^.va_flags<>QWORD(VNOVAL)) or
|
||||
(vap^.va_uid<>Integer(VNOVAL)) or
|
||||
(vap^.va_gid<>Integer(VNOVAL)) or
|
||||
(vap^.va_atime.tv_sec<>VNOVAL) or
|
||||
(vap^.va_mtime.tv_sec<>VNOVAL) or
|
||||
(vap^.va_mode<>Word(VNOVAL))
|
||||
) and
|
||||
((p_mount(vp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) then
|
||||
Exit(EROFS);
|
||||
|
||||
if (vap^.va_size<>QWORD(VNOVAL)) then
|
||||
begin
|
||||
case (vp^.v_type) of
|
||||
VDIR:
|
||||
begin
|
||||
Exit(EISDIR);
|
||||
end;
|
||||
VCHR,
|
||||
VBLK,
|
||||
VSOCK,
|
||||
VFIFO:
|
||||
begin
|
||||
if (vap^.va_flags<>QWORD(VNOVAL)) then
|
||||
Exit(EOPNOTSUPP);
|
||||
Exit(0);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
{
|
||||
* Disallow write attempts if the filesystem is
|
||||
* mounted read-only.
|
||||
}
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) then
|
||||
Exit(EROFS);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
{
|
||||
* We handle getattr only to change the fsid.
|
||||
}
|
||||
function null_getattr(ap:p_vop_getattr_args):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
begin
|
||||
error:=null_bypass(Pointer(ap));
|
||||
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
ap^.a_vap^.va_fsid:=p_mount(ap^.a_vp^.v_mount)^.mnt_stat.f_fsid.val[0];
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Handle to disallow write access if mounted read-only.
|
||||
}
|
||||
function null_access(ap:p_vop_access_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
accmode:accmode_t;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
accmode:=ap^.a_accmode;
|
||||
|
||||
{
|
||||
* Disallow write attempts on read-only layers;
|
||||
* unless the file is a socket, fifo, or a block or
|
||||
* character device resident on the filesystem.
|
||||
}
|
||||
if ((accmode and VWRITE)<>0) then
|
||||
begin
|
||||
case (vp^.v_type) of
|
||||
VDIR,
|
||||
VLNK,
|
||||
VREG:
|
||||
begin
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) then
|
||||
Exit(EROFS);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
function null_accessx(ap:p_vop_accessx_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
accmode:accmode_t;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
accmode:=ap^.a_accmode;
|
||||
|
||||
{
|
||||
* Disallow write attempts on read-only layers;
|
||||
* unless the file is a socket, fifo, or a block or
|
||||
* character device resident on the filesystem.
|
||||
}
|
||||
if ((accmode and VWRITE)<>0) then
|
||||
begin
|
||||
case (vp^.v_type) of
|
||||
VDIR,
|
||||
VLNK,
|
||||
VREG:
|
||||
begin
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_RDONLY)<>0) then
|
||||
Exit(EROFS);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
{
|
||||
* Increasing refcount of lower vnode is needed at least for the case
|
||||
* when lower FS is NFS to do sillyrename if the file is in use.
|
||||
* Unfortunately v_usecount is incremented in many places in
|
||||
* the kernel and, as such, there may be races that result in
|
||||
* the NFS client doing an extraneous silly rename, but that seems
|
||||
* preferable to not doing a silly rename when it is needed.
|
||||
}
|
||||
function null_remove(ap:p_vop_remove_args):Integer;
|
||||
var
|
||||
retval,vreleit:Integer;
|
||||
lvp,vp:p_vnode;
|
||||
tnn:p_null_node;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
if (vrefcnt(vp) > 1) then
|
||||
begin
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
VREF(lvp);
|
||||
vreleit:=1;
|
||||
end else
|
||||
vreleit:=0;
|
||||
|
||||
tnn:=VTONULL(vp);
|
||||
tnn^.null_flags:=tnn^.null_flags or NULLV_DROP;
|
||||
|
||||
retval:=null_bypass(@ap^.a_gen);
|
||||
if (vreleit<>0) then
|
||||
vrele(lvp);
|
||||
|
||||
Exit(retval);
|
||||
end;
|
||||
|
||||
{
|
||||
* We handle this to eliminate null FS to lower FS
|
||||
* file moving. Don't know why we don't allow this,
|
||||
* possibly we should.
|
||||
}
|
||||
function null_rename(ap:p_vop_rename_args):Integer;
|
||||
label
|
||||
_cross;
|
||||
var
|
||||
tdvp,fvp,fdvp,tvp:p_vnode;
|
||||
tnn:p_null_node;
|
||||
begin
|
||||
tdvp:=ap^.a_tdvp;
|
||||
fvp:=ap^.a_fvp;
|
||||
fdvp:=ap^.a_fdvp;
|
||||
tvp:=ap^.a_tvp;
|
||||
|
||||
if (tvp<>nil) then
|
||||
begin
|
||||
if (fvp^.v_mount<>tvp^.v_mount) then goto _cross;
|
||||
end;
|
||||
|
||||
{ Check for cross-device rename. }
|
||||
if (fvp^.v_mount<>tdvp^.v_mount) then
|
||||
begin
|
||||
_cross:
|
||||
if (tdvp=tvp) then
|
||||
vrele(tdvp)
|
||||
else
|
||||
vput(tdvp);
|
||||
|
||||
if (tvp<>nil) then
|
||||
vput(tvp);
|
||||
vrele(fdvp);
|
||||
vrele(fvp);
|
||||
Exit(EXDEV);
|
||||
end;
|
||||
|
||||
if (tvp<>nil) then
|
||||
begin
|
||||
tnn:=VTONULL(tvp);
|
||||
tnn^.null_flags:=tnn^.null_flags or NULLV_DROP;
|
||||
end;
|
||||
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
function null_rmdir(ap:p_vop_rmdir_args):Integer;
|
||||
var
|
||||
tnn:p_null_node;
|
||||
begin
|
||||
tnn:=VTONULL(ap^.a_vp);
|
||||
tnn^.null_flags:=tnn^.null_flags or NULLV_DROP;
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
{
|
||||
* We need to process our own vnode lock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
}
|
||||
function null_lock(ap:p_vop_lock1_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
flags:Integer;
|
||||
nn:p_null_node;
|
||||
lvp:p_vnode;
|
||||
error:Integer;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
flags:=ap^.a_flags;
|
||||
|
||||
if ((flags and LK_INTERLOCK)=0) then
|
||||
begin
|
||||
VI_LOCK(vp);
|
||||
flags:=flags or LK_INTERLOCK;
|
||||
ap^.a_flags:=flags;
|
||||
end;
|
||||
nn:=VTONULL(vp);
|
||||
{
|
||||
* If we're still active we must ask the lower layer to
|
||||
* lock as ffs has special lock considerations in it's
|
||||
* vop lock.
|
||||
}
|
||||
if (nn<>nil) then
|
||||
begin
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
if (lvp<>nil) then
|
||||
begin
|
||||
VI_LOCK(lvp);
|
||||
VI_UNLOCK(vp);
|
||||
{
|
||||
* We have to hold the vnode here to solve a potential
|
||||
* reclaim race. If we're forcibly vgone'd while we
|
||||
* still have refs, a thread could be sleeping inside
|
||||
* the lowervp's vop_lock routine. When we vgone we will
|
||||
* drop our last ref to the lowervp, which would allow it
|
||||
* to be reclaimed. The lowervp could then be recycled,
|
||||
* in which case it is not legal to be sleeping in it's VOP.
|
||||
* We prevent it from being recycled by holding the vnode
|
||||
* here.
|
||||
}
|
||||
vholdl(lvp);
|
||||
error:=VOP_LOCK(lvp,flags,{$INCLUDE %FILE%},{$INCLUDE %LINENUM%});
|
||||
|
||||
{
|
||||
* We might have slept to get the lock and someone might have
|
||||
* clean our vnode already, switching vnode lock from one in
|
||||
* lowervp to v_lock in our own vnode structure. Handle this
|
||||
* case by reacquiring correct lock in requested mode.
|
||||
}
|
||||
if (VTONULL(vp)=nil) and (error=0) then
|
||||
begin
|
||||
ap^.a_flags:=ap^.a_flags and (not (LK_TYPE_MASK or LK_INTERLOCK));
|
||||
case (flags and LK_TYPE_MASK) of
|
||||
LK_SHARED:
|
||||
begin
|
||||
ap^.a_flags:=ap^.a_flags or LK_SHARED;
|
||||
end;
|
||||
LK_UPGRADE,
|
||||
LK_EXCLUSIVE:
|
||||
begin
|
||||
ap^.a_flags:=ap^.a_flags or LK_EXCLUSIVE;
|
||||
end;
|
||||
else
|
||||
Assert(False,'Unsupported lock request');
|
||||
end;
|
||||
VOP_UNLOCK(lvp, 0);
|
||||
error:=vop_stdlock(ap);
|
||||
end;
|
||||
vdrop(lvp);
|
||||
end else
|
||||
error:=vop_stdlock(ap);
|
||||
end else
|
||||
error:=vop_stdlock(ap);
|
||||
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
{
|
||||
* We need to process our own vnode unlock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
}
|
||||
function null_unlock(ap:p_vop_unlock_args):Integer;
|
||||
label
|
||||
_else;
|
||||
var
|
||||
vp:p_vnode;
|
||||
flags:Integer;
|
||||
mtxlkflag:Integer;
|
||||
nn:p_null_node;
|
||||
lvp:p_vnode;
|
||||
error:Integer;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
flags:=ap^.a_flags;
|
||||
mtxlkflag:=0;
|
||||
|
||||
if ((flags and LK_INTERLOCK)<>0) then
|
||||
mtxlkflag:=1
|
||||
else
|
||||
if (not mtx_owned(VI_MTX(vp)^)) then
|
||||
begin
|
||||
VI_LOCK(vp);
|
||||
mtxlkflag:=2;
|
||||
end;
|
||||
nn:=VTONULL(vp);
|
||||
if (nn<>nil) then
|
||||
begin
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
if (lvp=nil) then goto _else;
|
||||
|
||||
VI_LOCK(lvp);
|
||||
flags:=flags or LK_INTERLOCK;
|
||||
vholdl(lvp);
|
||||
VI_UNLOCK(vp);
|
||||
error:=VOP_UNLOCK(lvp, flags);
|
||||
vdrop(lvp);
|
||||
if (mtxlkflag=0) then
|
||||
VI_LOCK(vp);
|
||||
end else
|
||||
begin
|
||||
_else:
|
||||
if (mtxlkflag=2) then
|
||||
VI_UNLOCK(vp);
|
||||
error:=vop_stdunlock(ap);
|
||||
end;
|
||||
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
{
|
||||
* Do not allow the VOP_INACTIVE to be passed to the lower layer,
|
||||
* since the reference count on the lower vnode is not related to
|
||||
* ours.
|
||||
}
|
||||
function null_inactive(ap:p_vop_inactive_args):Integer;
|
||||
var
|
||||
vp,lvp:p_vnode;
|
||||
xp:p_null_node;
|
||||
mp:p_mount;
|
||||
xmp:p_null_mount;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
xp:=VTONULL(vp);
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
mp:=vp^.v_mount;
|
||||
xmp:=MOUNTTONULLMOUNT(mp);
|
||||
|
||||
if ((xmp^.nullm_flags and NULLM_CACHE)=0) or
|
||||
((xp^.null_flags and NULLV_DROP)<>0) or
|
||||
((lvp^.v_vflag and VV_NOSYNC)<>0) then
|
||||
begin
|
||||
{
|
||||
* If this is the last reference and caching of the
|
||||
* nullfs vnodes is not enabled, or the lower vnode is
|
||||
* deleted, then free up the vnode so as not to tie up
|
||||
* the lower vnodes.
|
||||
}
|
||||
//vp^.v_object:=nil;
|
||||
vrecycle(vp);
|
||||
end;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Now, the nullfs vnode and, due to the sharing lock, the lower
|
||||
* vnode, are exclusively locked, and we shall destroy the null vnode.
|
||||
}
|
||||
function null_reclaim(ap:p_vop_reclaim_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
xp:p_null_node;
|
||||
lowervp:p_vnode;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
xp:=VTONULL(vp);
|
||||
lowervp:=xp^.null_lowervp;
|
||||
|
||||
Assert((lowervp<>nil) and (vp^.v_vnlock<>@vp^.v_lock),'Reclaiming incomplete null vnode');
|
||||
|
||||
null_hashrem(xp);
|
||||
{
|
||||
* Use the interlock to protect the clearing of v_data to
|
||||
* prevent faults in null_lock().
|
||||
}
|
||||
mtx_lock(vp^.v_lock);
|
||||
//lockmgr(@vp^.v_lock, LK_EXCLUSIVE, nil);
|
||||
|
||||
VI_LOCK(vp);
|
||||
vp^.v_data:=nil;
|
||||
//vp^.v_object:=nil;
|
||||
vp^.v_vnlock:=@vp^.v_lock;
|
||||
VI_UNLOCK(vp);
|
||||
|
||||
{
|
||||
* If we were opened for write, we leased one write reference
|
||||
* to the lower vnode. If this is a reclamation due to the
|
||||
* forced unmount, undo the reference now.
|
||||
}
|
||||
if (vp^.v_writecount > 0) then
|
||||
VOP_ADD_WRITECOUNT(lowervp, -1);
|
||||
|
||||
if ((xp^.null_flags and NULLV_NOUNLOCK)<>0) then
|
||||
vunref(lowervp)
|
||||
else
|
||||
vput(lowervp);
|
||||
|
||||
FreeMem(xp);
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function null_print(ap:p_vop_print_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
|
||||
Writeln(Format('vp=%p, lowervp=%p', [vp,VTONULL(vp)^.null_lowervp]));
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{ ARGSUSED }
|
||||
function null_getwritemount(ap:p_vop_getwritemount_args):Integer;
|
||||
label
|
||||
_else;
|
||||
var
|
||||
xp:p_null_node;
|
||||
lowervp:p_vnode;
|
||||
vp:p_vnode;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
VI_LOCK(vp);
|
||||
xp:=VTONULL(vp);
|
||||
if (xp<>nil) then
|
||||
begin
|
||||
lowervp:=xp^.null_lowervp;
|
||||
if (lowervp=nil) then goto _else;
|
||||
|
||||
VI_LOCK(lowervp);
|
||||
VI_UNLOCK(vp);
|
||||
vholdl(lowervp);
|
||||
VI_UNLOCK(lowervp);
|
||||
VOP_GETWRITEMOUNT(lowervp, ap^.a_mpp);
|
||||
vdrop(lowervp);
|
||||
end else
|
||||
begin
|
||||
_else:
|
||||
VI_UNLOCK(vp);
|
||||
ap^.a_mpp^:=nil;
|
||||
end;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function null_vptofh(ap:p_vop_vptofh_args):Integer;
|
||||
var
|
||||
lvp:p_vnode;
|
||||
begin
|
||||
lvp:=NULLVPTOLOWERVP(ap^.a_vp);
|
||||
Exit(VOP_VPTOFH(lvp, ap^.a_fhp));
|
||||
end;
|
||||
|
||||
function null_vptocnp(ap:p_vop_vptocnp_args):Integer;
|
||||
var
|
||||
vp:p_vnode;
|
||||
dvp:pp_vnode;
|
||||
lvp,ldvp:p_vnode;
|
||||
error,locked:Integer;
|
||||
begin
|
||||
vp:=ap^.a_vp;
|
||||
dvp:=ap^.a_vpp;
|
||||
|
||||
if (vp^.v_type=VDIR) then
|
||||
Exit(vop_stdvptocnp(ap));
|
||||
|
||||
locked:=VOP_ISLOCKED(vp);
|
||||
lvp:=NULLVPTOLOWERVP(vp);
|
||||
vhold(lvp);
|
||||
VOP_UNLOCK(vp, 0); { vp is held by vn_vptocnp_locked that called us }
|
||||
ldvp:=lvp;
|
||||
vref(lvp);
|
||||
error:=0;
|
||||
Assert(False,'TODO vn_vptocnp');
|
||||
//error:=vn_vptocnp(@ldvp, ap^.a_buf, ap^.a_buflen);
|
||||
vdrop(lvp);
|
||||
if (error<>0) then
|
||||
begin
|
||||
vn_lock(vp, locked or LK_RETRY);
|
||||
Exit(ENOENT);
|
||||
end;
|
||||
|
||||
{
|
||||
* Exclusive lock is required by insmntque1 call in
|
||||
* null_nodeget()
|
||||
}
|
||||
error:=vn_lock(ldvp, LK_EXCLUSIVE);
|
||||
if (error<>0) then
|
||||
begin
|
||||
vrele(ldvp);
|
||||
vn_lock(vp, locked or LK_RETRY);
|
||||
Exit(ENOENT);
|
||||
end;
|
||||
vref(ldvp);
|
||||
error:=null_nodeget(vp^.v_mount, ldvp, dvp);
|
||||
if (error=0) then
|
||||
begin
|
||||
VOP_UNLOCK(dvp^, 0); { keep reference on *dvp }
|
||||
end;
|
||||
vn_lock(vp, locked or LK_RETRY);
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
function null_link(ap:p_vop_link_args):Integer;
|
||||
begin
|
||||
if (ap^.a_tdvp^.v_mount<>ap^.a_vp^.v_mount) then
|
||||
Exit(EXDEV);
|
||||
|
||||
Exit(null_bypass(Pointer(ap)));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
unit nullfs;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
mqueue,
|
||||
vmount,
|
||||
vnode;
|
||||
|
||||
const
|
||||
NULLM_CACHE=$0001;
|
||||
|
||||
NULLV_NOUNLOCK=$0001;
|
||||
NULLV_DROP =$0002;
|
||||
|
||||
type
|
||||
p_null_mount=^t_null_mount;
|
||||
t_null_mount=packed record
|
||||
nullm_vfs :p_mount;
|
||||
nullm_rootvp:p_vnode; { Reference to root null_node }
|
||||
nullm_flags :QWORD;
|
||||
end;
|
||||
|
||||
p_null_node=^t_null_node;
|
||||
t_null_node=packed record
|
||||
null_hash :LIST_ENTRY; { Hash list }
|
||||
null_lowervp:p_vnode; { VREFed once }
|
||||
null_vnode :p_vnode; { Back pointer }
|
||||
null_flags :DWORD;
|
||||
end;
|
||||
|
||||
function MOUNTTONULLMOUNT(mp:p_mount):p_null_mount;
|
||||
function VTONULL(vp:p_vnode):p_null_node;
|
||||
function NULLTOV(xp:p_null_node):p_vnode;
|
||||
function NULLVPTOLOWERVP(vp:p_vnode):p_vnode;
|
||||
|
||||
implementation
|
||||
|
||||
function MOUNTTONULLMOUNT(mp:p_mount):p_null_mount;
|
||||
begin
|
||||
Result:=mp^.mnt_data;
|
||||
end;
|
||||
|
||||
function VTONULL(vp:p_vnode):p_null_node;
|
||||
begin
|
||||
Result:=vp^.v_data;
|
||||
end;
|
||||
|
||||
function NULLTOV(xp:p_null_node):p_vnode;
|
||||
begin
|
||||
Result:=xp^.null_vnode;
|
||||
end;
|
||||
|
||||
function NULLVPTOLOWERVP(vp:p_vnode):p_vnode;
|
||||
begin
|
||||
Result:=VTONULL(vp)^.null_lowervp;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -9,8 +9,8 @@ uses
|
|||
ntapi;
|
||||
|
||||
const
|
||||
IOSIZE_MAX =High(Int64);
|
||||
DEVFS_IOSIZE_MAX=High(Int64);
|
||||
IOSIZE_MAX =High(Integer);
|
||||
DEVFS_IOSIZE_MAX=High(Integer);
|
||||
|
||||
function copystr(from,_to:Pointer;maxlen:ptruint;lencopied:pptruint):Integer;
|
||||
function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline;
|
||||
|
|
|
@ -31,6 +31,7 @@ uses
|
|||
devfs_devs,
|
||||
devfs_vfsops,
|
||||
fdesc_vfsops,
|
||||
null_vfsops,
|
||||
kern_descrip,
|
||||
vfs_mountroot;
|
||||
|
||||
|
@ -44,6 +45,7 @@ procedure module_init;
|
|||
begin
|
||||
vfs_register(@devfs_vfsconf);
|
||||
vfs_register(@fdescfs_vfsconf);
|
||||
vfs_register(@nullfs_vfsconf);
|
||||
vfs_mountroot.vfs_mountroot();
|
||||
fildesc_drvinit;
|
||||
end;
|
||||
|
|
|
@ -257,10 +257,6 @@
|
|||
<Filename Value="..\..\rtl\murmurhash.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\vfs\vfs_vnode.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\vfs\vfs_mount.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
@ -453,10 +449,6 @@
|
|||
<Filename Value="..\sce_errno.inc"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\fdescfs\fdesc.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\fdescfs\fdesc_vfsops.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
@ -469,6 +461,30 @@
|
|||
<Filename Value="..\kern\subr_hash.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\nullfs\nullfs.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\fdescfs\fdescfs.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\vfs\vnode.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\nullfs\null_subr.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\nullfs\null_vnops.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\fs\nullfs\null_vfsops.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -479,7 +495,7 @@
|
|||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir);.."/>
|
||||
<OtherUnitFiles Value="..;..\..\rtl;..\..\kernel\libthr;..\kern;..\vm;..\vfs;..\fs\deadfs;..\fs\devfs;..\fs\fdescfs"/>
|
||||
<OtherUnitFiles Value="..;..\..\rtl;..\..\kernel\libthr;..\kern;..\vm;..\vfs;..\fs\deadfs;..\fs\devfs;..\fs\fdescfs;..\fs\nullfs"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
|
|
|
@ -39,7 +39,6 @@ uses
|
|||
thr_stack,
|
||||
sys_mmap,
|
||||
kern_synch,
|
||||
vfs_vnode,
|
||||
murmurhash,
|
||||
hamt,
|
||||
vfs_subr,
|
||||
|
@ -63,10 +62,15 @@ uses
|
|||
vstat,
|
||||
vfcntl,
|
||||
vdirent,
|
||||
fdesc,
|
||||
fdesc_vfsops,
|
||||
fdesc_vnops,
|
||||
kern_descrip;
|
||||
fdescfs,
|
||||
kern_descrip,
|
||||
vnode,
|
||||
nullfs,
|
||||
null_subr,
|
||||
null_vnops,
|
||||
null_vfsops;
|
||||
|
||||
var
|
||||
mtx:umutex;
|
||||
|
|
28
sys/time.pas
28
sys/time.pas
|
@ -69,16 +69,16 @@ procedure timevalfix(t1:ptimeval);
|
|||
procedure timevaladd(t1,t2:ptimeval);
|
||||
procedure timevalsub(t1,t2:ptimeval);
|
||||
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline;
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer;
|
||||
|
||||
procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec); inline;
|
||||
procedure TIMESPEC_TO_TIMEVAL(tv:ptimeval;ts:ptimespec); inline;
|
||||
procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec);
|
||||
procedure TIMESPEC_TO_TIMEVAL(tv:ptimeval;ts:ptimespec);
|
||||
|
||||
function TIMESPEC_TO_UNIT(ts:ptimespec):Int64; inline; //Unit
|
||||
function TIMEVAL_TO_UNIT (tv:ptimeval ):Int64; inline; //Unit
|
||||
function USEC_TO_UNIT (usec:QWORD ):Int64; inline; //Unit
|
||||
function TIMESPEC_TO_UNIT(ts:ptimespec):Int64; //Unit
|
||||
function TIMEVAL_TO_UNIT (tv:ptimeval ):Int64; //Unit
|
||||
function USEC_TO_UNIT (usec:QWORD ):Int64; //Unit
|
||||
|
||||
function tvtohz(time:Int64):Int64; inline;
|
||||
function tvtohz(time:Int64):Int64;
|
||||
procedure usec2timespec(ts:ptimespec;timeo:DWORD);
|
||||
|
||||
procedure TIMESPEC_ADD(dst,src,val:ptimespec);
|
||||
|
@ -158,7 +158,7 @@ begin
|
|||
timevalfix(t1);
|
||||
end;
|
||||
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline;
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer;
|
||||
begin
|
||||
if (tvp^.tv_sec=uvp^.tv_sec) then
|
||||
begin
|
||||
|
@ -169,34 +169,34 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec); inline;
|
||||
procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec);
|
||||
begin
|
||||
ts^.tv_sec :=tv^.tv_sec;
|
||||
ts^.tv_nsec:=tv^.tv_usec * 1000;
|
||||
end;
|
||||
|
||||
procedure TIMESPEC_TO_TIMEVAL(tv:ptimeval;ts:ptimespec); inline;
|
||||
procedure TIMESPEC_TO_TIMEVAL(tv:ptimeval;ts:ptimespec);
|
||||
begin
|
||||
tv^.tv_sec :=ts^.tv_sec;
|
||||
tv^.tv_usec:=ts^.tv_nsec div 1000;
|
||||
end;
|
||||
|
||||
function TIMESPEC_TO_UNIT(ts:ptimespec):Int64; inline; //Unit
|
||||
function TIMESPEC_TO_UNIT(ts:ptimespec):Int64; //Unit
|
||||
begin
|
||||
Result:=(QWORD(ts^.tv_sec)*10000000)+(QWORD(ts^.tv_nsec) div 100);
|
||||
end;
|
||||
|
||||
function TIMEVAL_TO_UNIT(tv:ptimeval):Int64; inline; //Unit
|
||||
function TIMEVAL_TO_UNIT(tv:ptimeval):Int64; //Unit
|
||||
begin
|
||||
Result:=(QWORD(tv^.tv_sec)*10000000)+(QWORD(tv^.tv_usec)*10);
|
||||
end;
|
||||
|
||||
function USEC_TO_UNIT(usec:QWORD):Int64; inline; //Unit
|
||||
function USEC_TO_UNIT(usec:QWORD):Int64; //Unit
|
||||
begin
|
||||
Result:=(usec*10);
|
||||
end;
|
||||
|
||||
function tvtohz(time:Int64):Int64; inline;
|
||||
function tvtohz(time:Int64):Int64;
|
||||
begin
|
||||
Result:=time;
|
||||
end;
|
||||
|
|
|
@ -10,7 +10,7 @@ uses
|
|||
vmount,
|
||||
vfile,
|
||||
vuio,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
time,
|
||||
vm,
|
||||
vm_object,
|
||||
|
@ -1159,6 +1159,7 @@ function make_dev_physpath_alias(flags:Integer;
|
|||
pdev,old_alias:p_cdev;
|
||||
physpath:PChar):Integer;
|
||||
label
|
||||
_ret,
|
||||
_out;
|
||||
var
|
||||
devfspath:PChar;
|
||||
|
@ -1203,8 +1204,11 @@ begin
|
|||
R:=Format('%s/%s',[physpath,pdev^.si_name]);
|
||||
Move(PChar(R)^,devfspath^,Length(R)+1);
|
||||
|
||||
if (old_alias<>nil) and (strcomp(old_alias^.si_name, devfspath)=0) then
|
||||
if (old_alias=nil) then goto _ret;
|
||||
|
||||
if (strcomp(old_alias^.si_name, devfspath)=0) then
|
||||
begin
|
||||
_ret:
|
||||
{ Retain the existing alias. }
|
||||
cdev^:=old_alias;
|
||||
old_alias:=nil;
|
||||
|
@ -1271,8 +1275,9 @@ begin
|
|||
|
||||
csw:=dev^.si_devsw;
|
||||
dev^.si_devsw:=nil; { already nil for SI_ALIAS }
|
||||
while (csw<>nil) and (csw^.d_purge<>nil) and (dev^.si_threadcount<>0) do
|
||||
while (csw<>nil) and (dev^.si_threadcount<>0) do
|
||||
begin
|
||||
if (csw^.d_purge=nil) then Break;
|
||||
csw^.d_purge(dev);
|
||||
msleep(csw, @devmtx, PRIBIO, 'devprg', hz div 10);
|
||||
if (dev^.si_threadcount<>0) then
|
||||
|
|
|
@ -15,7 +15,7 @@ uses
|
|||
vfcntl,
|
||||
vfilio,
|
||||
vmount,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vsocketvar;
|
||||
|
||||
const
|
||||
|
|
|
@ -135,6 +135,7 @@ var
|
|||
c:p_capability;
|
||||
error:Integer;
|
||||
begin
|
||||
if (fp_cap=nil) then Exit(EINVAL);
|
||||
if (fp_cap^.f_type<>DTYPE_CAPABILITY) then
|
||||
begin
|
||||
fpp^:=fp_cap;
|
||||
|
|
|
@ -8,7 +8,7 @@ interface
|
|||
uses
|
||||
vstat,
|
||||
vuio,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
kern_thr,
|
||||
kern_id;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ interface
|
|||
|
||||
uses
|
||||
vfile,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
kern_rwlock,
|
||||
kern_id;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ interface
|
|||
|
||||
uses
|
||||
sysutils,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vnode_if,
|
||||
vdirent,
|
||||
vuio,
|
||||
|
@ -17,7 +17,6 @@ uses
|
|||
vnamei,
|
||||
vfcntl,
|
||||
vpoll,
|
||||
vsocketvar,
|
||||
kern_thr,
|
||||
kern_mtx;
|
||||
|
||||
|
@ -573,6 +572,8 @@ var
|
|||
begin
|
||||
vp:=ap^.a_vp;
|
||||
|
||||
//Writeln('vop_std lock:',HexStr(ap^.a_vp^.v_vnlock));
|
||||
|
||||
Result:=lockmgr(vp^.v_vnlock,ap^.a_flags,VI_MTX(vp));
|
||||
|
||||
//Exit(_lockmgr_args(vp^.v_vnlock, ap^.a_flags, VI_MTX(vp),
|
||||
|
@ -587,6 +588,8 @@ var
|
|||
begin
|
||||
vp:=ap^.a_vp;
|
||||
|
||||
//Writeln('vop_stdunlock:',HexStr(ap^.a_vp^.v_vnlock));
|
||||
|
||||
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)));
|
||||
|
@ -596,6 +599,8 @@ end;
|
|||
function vop_stdislocked(ap:p_vop_islocked_args):Integer;
|
||||
begin
|
||||
|
||||
//Writeln('vop_stdislocked:',HexStr(ap^.a_vp^.v_vnlock),':',mtx_owned(ap^.a_vp^.v_vnlock^));
|
||||
|
||||
if mtx_owned(ap^.a_vp^.v_vnlock^) then
|
||||
Exit(LK_EXCLUSIVE)
|
||||
else
|
||||
|
|
|
@ -13,7 +13,7 @@ uses
|
|||
vfile,
|
||||
vfiledesc,
|
||||
vfcntl,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vnode_if,
|
||||
vnamei,
|
||||
vmount,
|
||||
|
@ -316,13 +316,20 @@ end;
|
|||
|
||||
function compute_cn_lkflags(mp:p_mount;lkflags,cnflags:Integer):Integer;
|
||||
begin
|
||||
if (mp=nil) or (((lkflags and LK_SHARED)<>0) and
|
||||
if (mp=nil) then
|
||||
begin
|
||||
lkflags:=lkflags and (not LK_SHARED);
|
||||
lkflags:=lkflags or LK_EXCLUSIVE;
|
||||
Exit(lkflags);
|
||||
end;
|
||||
|
||||
if (((lkflags and LK_SHARED)<>0) and
|
||||
(((mp^.mnt_kern_flag and MNTK_LOOKUP_SHARED)=0) or
|
||||
(((cnflags and ISDOTDOT)<>0) and
|
||||
((mp^.mnt_kern_flag and MNTK_LOOKUP_EXCL_DOTDOT)<>0)))) then
|
||||
begin
|
||||
lkflags:=lkflags and (not LK_SHARED);
|
||||
lkflags:=lkflags or LK_EXCLUSIVE;
|
||||
lkflags:=lkflags or LK_EXCLUSIVE;
|
||||
end;
|
||||
Exit(lkflags);
|
||||
end;
|
||||
|
@ -348,11 +355,12 @@ begin
|
|||
}
|
||||
if ((flags and ISOPEN)<>0) then
|
||||
begin
|
||||
if (mp<>nil) and
|
||||
((mp^.mnt_kern_flag and MNTK_EXTENDED_SHARED)<>0) then
|
||||
if (mp<>nil) then
|
||||
if ((mp^.mnt_kern_flag and MNTK_EXTENDED_SHARED)<>0) then
|
||||
begin
|
||||
Exit(0)
|
||||
else
|
||||
Exit(1);
|
||||
end;
|
||||
Exit(1);
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -674,8 +682,8 @@ unionlookup:
|
|||
|
||||
if (error=ENOENT) and
|
||||
((dp^.v_vflag and VV_ROOT)<>0) and
|
||||
(dp^.v_mount<>nil) and
|
||||
((p_mount(dp^.v_mount)^.mnt_flag and MNT_UNION)<>0) then
|
||||
(dp^.v_mount<>nil) then
|
||||
if ((p_mount(dp^.v_mount)^.mnt_flag and MNT_UNION)<>0) then
|
||||
begin
|
||||
tdp:=dp;
|
||||
dp:=p_mount(dp^.v_mount)^.mnt_vnodecovered;
|
||||
|
@ -684,9 +692,7 @@ unionlookup:
|
|||
VREF(dp);
|
||||
vput(tdp);
|
||||
VFS_UNLOCK_GIANT(tvfslocked);
|
||||
vn_lock(dp,
|
||||
compute_cn_lkflags(dp^.v_mount, cnp^.cn_lkflags or
|
||||
LK_RETRY, cnp^.cn_flags));
|
||||
vn_lock(dp,compute_cn_lkflags(dp^.v_mount, cnp^.cn_lkflags or LK_RETRY, cnp^.cn_flags));
|
||||
goto unionlookup;
|
||||
end;
|
||||
|
||||
|
@ -883,8 +889,8 @@ success:
|
|||
* Because of lookup_shared we may have the vnode shared locked, but
|
||||
* the caller may want it to be exclusively locked.
|
||||
}
|
||||
if (needs_exclusive_leaf(dp^.v_mount, cnp^.cn_flags) and
|
||||
VOP_ISLOCKED(dp)<>LK_EXCLUSIVE) then
|
||||
if (needs_exclusive_leaf(dp^.v_mount, cnp^.cn_flags)<>0) and
|
||||
(VOP_ISLOCKED(dp)<>LK_EXCLUSIVE) then
|
||||
begin
|
||||
vn_lock(dp, LK_UPGRADE or LK_RETRY);
|
||||
if ((dp^.v_iflag and VI_DOOMED)<>0) then
|
||||
|
|
|
@ -14,7 +14,7 @@ uses
|
|||
kern_mtx,
|
||||
kern_synch,
|
||||
kern_thr,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfs_init,
|
||||
vfs_lookup,
|
||||
vnode_if;
|
||||
|
@ -103,6 +103,7 @@ function kernel_mount(ma:p_mntarg;flags:QWORD):Integer;
|
|||
implementation
|
||||
|
||||
uses
|
||||
murmurhash,
|
||||
errno,
|
||||
systm,
|
||||
vfs_vnops,
|
||||
|
@ -723,6 +724,18 @@ begin
|
|||
mtx_destroy(mp^.mnt_mtx);
|
||||
end;
|
||||
|
||||
var
|
||||
mnt_hashseed:QWORD=QWORD($FEEDBABEFEEDBABE);
|
||||
|
||||
function get_mnt_hashseed:DWORD;
|
||||
var
|
||||
i:QWORD;
|
||||
begin
|
||||
i:=MurmurHash64A(@mnt_hashseed,SizeOf(mnt_hashseed),mnt_hashseed);
|
||||
mnt_hashseed:=i;
|
||||
Result:=DWORD(i);
|
||||
end;
|
||||
|
||||
function vfs_mount_alloc(vp :p_vnode;
|
||||
vfsp :p_vfsconf;
|
||||
fspath:PChar):p_mount;
|
||||
|
@ -755,7 +768,8 @@ begin
|
|||
//mac_mount_init(mp);
|
||||
//mac_mount_create(cred, mp);
|
||||
|
||||
mp^.mnt_hashseed:=$FEEDBABE; //arc4rand
|
||||
//arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
|
||||
mp^.mnt_hashseed:=get_mnt_hashseed;
|
||||
|
||||
TAILQ_INIT(@mp^.mnt_uppers);
|
||||
Result:=mp;
|
||||
|
|
|
@ -19,7 +19,7 @@ uses
|
|||
errno,
|
||||
vuio,
|
||||
vnamei,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vnode_if,
|
||||
vfiledesc,
|
||||
vfs_subr,
|
||||
|
@ -68,7 +68,10 @@ var
|
|||
val,val_arg:PChar;
|
||||
opts:PChar;
|
||||
begin
|
||||
if (options=nil) or (options[0]=#0) then
|
||||
if (options=nil) then
|
||||
Exit(ma);
|
||||
|
||||
if (options[0]=#0) then
|
||||
Exit(ma);
|
||||
|
||||
p:=strdup(options);
|
||||
|
@ -165,11 +168,11 @@ begin
|
|||
mpp^:=mp;
|
||||
set_rootvnode();
|
||||
|
||||
error:=kern_symlink('/', 'dev', UIO_SYSSPACE);
|
||||
if (error<>0) then
|
||||
begin
|
||||
Writeln('kern_symlink /dev / returns ',error);
|
||||
end;
|
||||
//error:=kern_symlink('/', 'dev', UIO_SYSSPACE);
|
||||
//if (error<>0) then
|
||||
//begin
|
||||
// Writeln('kern_symlink /dev / returns ',error);
|
||||
//end;
|
||||
|
||||
Exit(error);
|
||||
end;
|
||||
|
@ -296,9 +299,9 @@ begin
|
|||
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);
|
||||
//error:=kern_unlink('/dev/dev', UIO_SYSSPACE);
|
||||
//if (error<>0) then
|
||||
// Writeln('mountroot: unable to unlink /dev/dev ', error);
|
||||
end;
|
||||
|
||||
Exit(0);
|
||||
|
@ -332,26 +335,23 @@ begin
|
|||
end;
|
||||
|
||||
procedure vfs_mountroot();
|
||||
label
|
||||
_end;
|
||||
var
|
||||
mp:p_mount;
|
||||
//opt:p_vfsoptlist;
|
||||
error:Integer;
|
||||
begin
|
||||
mtx_lock(VFS_Giant);
|
||||
|
||||
error:=vfs_mountroot_devfs(@mp);
|
||||
if (error<>0) then goto _end;
|
||||
|
||||
//opt:=nil;
|
||||
//vfs_domount('fdescfs','/dev/fd',MNT_RDONLY,@opt);
|
||||
error:=vfs_mountroot_simple('nullfs','/','',nil,MNT_RDONLY or MNT_ROOTFS);
|
||||
if (error<>0) then goto _end;
|
||||
|
||||
//error:=vfs_mountroot_simple('fdescfs','/dev/fd','',nil,0);
|
||||
//error:=vfs_mountroot_simple('fdescfs','/fd','',nil,0);
|
||||
|
||||
//if (error=0) then
|
||||
//begin
|
||||
// error:=vfs_mountroot_shuffle(mp);
|
||||
//end;
|
||||
error:=vfs_mountroot_shuffle(mp);
|
||||
|
||||
_end:
|
||||
mtx_unlock(VFS_Giant);
|
||||
end;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ uses
|
|||
vmount,
|
||||
vfile,
|
||||
vstat,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vnode_if,
|
||||
vdirent,
|
||||
vfcntl,
|
||||
|
@ -45,14 +45,14 @@ procedure vgone(vp:p_vnode);
|
|||
|
||||
function vget(vp:p_vnode;flags:Integer):Integer;
|
||||
procedure vref(vp:p_vnode);
|
||||
function vrefcnt(vp:p_vnode):Integer;
|
||||
procedure vrele(vp:p_vnode);
|
||||
procedure vput(vp:p_vnode);
|
||||
procedure vunref(vp:p_vnode);
|
||||
|
||||
procedure vinactive(vp:p_vnode);
|
||||
function vflush(mp:p_mount;rootrefs,flags:Integer):Integer;
|
||||
|
||||
procedure vfs_notify_upper(vp:p_vnode;event:Integer);
|
||||
|
||||
procedure assert_vi_locked (vp:p_vnode;str:PChar);
|
||||
procedure assert_vi_unlocked (vp:p_vnode;str:PChar);
|
||||
procedure assert_vop_locked (vp:p_vnode;str:PChar);
|
||||
|
@ -122,18 +122,6 @@ procedure __mnt_vnode_markerfree_active(mvp:pp_vnode;mp:p_mount);
|
|||
procedure vntblinit; //SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vntblinit, NULL);
|
||||
procedure vnlru_proc(); //SYSINIT(vnlru, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, @vnlru_kp);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
vfs_vnops,
|
||||
subr_uio,
|
||||
vm_object,
|
||||
vsys_generic,
|
||||
dead_vnops,
|
||||
rtprio,
|
||||
kern_conf;
|
||||
|
||||
{
|
||||
* List of vnodes that are ready for recycling.
|
||||
}
|
||||
|
@ -180,6 +168,18 @@ var
|
|||
freevnodes :Integer=0;
|
||||
vnlru_nowhere :Integer=0;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
vfs_vnops,
|
||||
subr_uio,
|
||||
vm_object,
|
||||
vsys_generic,
|
||||
dead_vnops,
|
||||
rtprio,
|
||||
kern_conf;
|
||||
|
||||
{
|
||||
* Macros to control when a vnode is freed and recycled. All require
|
||||
* the vnode interlock.
|
||||
|
@ -406,8 +406,9 @@ begin
|
|||
while (count<>0) do
|
||||
begin
|
||||
vp:=TAILQ_FIRST(@mp^.mnt_nvnodelist);
|
||||
while (vp<>nil) and (vp^.v_type=VMARKER) do
|
||||
while (vp<>nil) do
|
||||
begin
|
||||
if (vp^.v_type<>VMARKER) then Break;
|
||||
vp:=TAILQ_NEXT(vp,@vp^.v_nmntvnodes);
|
||||
end;
|
||||
if (vp=nil) then
|
||||
|
@ -705,7 +706,7 @@ var
|
|||
td:p_kthread;
|
||||
vp:p_vnode;
|
||||
//struct bufobj *bo;
|
||||
error:Integer;
|
||||
error,susp:Integer;
|
||||
begin
|
||||
vp:=nil;
|
||||
td:=curkthread;
|
||||
|
@ -723,7 +724,13 @@ begin
|
|||
}
|
||||
if (freevnodes > wantfreevnodes) then
|
||||
vnlru_free(1);
|
||||
error:=getnewvnode_wait(ord((mp<>nil) and ((mp^.mnt_kern_flag and MNTK_SUSPEND)<>0)));
|
||||
|
||||
susp:=ord(False);
|
||||
if (mp<>nil) then
|
||||
begin
|
||||
susp:=ord(((mp^.mnt_kern_flag and MNTK_SUSPEND)<>0));
|
||||
end;
|
||||
error:=getnewvnode_wait(susp);
|
||||
|
||||
System.InterlockedIncrement64(numvnodes);
|
||||
mtx_unlock(vnode_free_list_mtx);
|
||||
|
@ -785,7 +792,7 @@ begin
|
|||
* E.g., nilfs uses vfs_hash_index() on the lower vnode for
|
||||
* its own hashing.
|
||||
}
|
||||
vp^.v_hash:=ptrint(vp) shr vnsz2log;
|
||||
vp^.v_hash:=ptruint(vp) shr vnsz2log;
|
||||
|
||||
vpp^:=vp;
|
||||
Exit(0);
|
||||
|
@ -2233,7 +2240,8 @@ begin
|
|||
}
|
||||
obj:=nil;
|
||||
//obj:=vp^.v_object;
|
||||
if (obj<>nil) and ((obj^.flags and OBJ_MIGHTBEDIRTY)<>0) then
|
||||
if (obj<>nil) then
|
||||
if ((obj^.flags and OBJ_MIGHTBEDIRTY)<>0) then
|
||||
begin
|
||||
VM_OBJECT_LOCK(obj);
|
||||
//vm_object_page_clean(obj, 0, 0, OBJPC_NOSYNC);
|
||||
|
@ -2432,87 +2440,6 @@ begin
|
|||
VI_UNLOCK(vp);
|
||||
end;
|
||||
|
||||
procedure notify_lowervp_vfs_dummy(mp:p_mount;lowervp:p_vnode);
|
||||
begin
|
||||
end;
|
||||
|
||||
const
|
||||
vgonel_vfsops:vfsops=(
|
||||
vfs_mount :nil;
|
||||
vfs_cmount :nil;
|
||||
vfs_unmount :nil;
|
||||
vfs_root :nil;
|
||||
vfs_quotactl :nil;
|
||||
vfs_statfs :nil;
|
||||
vfs_sync :nil;
|
||||
vfs_vget :nil;
|
||||
vfs_fhtovp :nil;
|
||||
vfs_checkexp :nil;
|
||||
vfs_init :nil;
|
||||
vfs_uninit :nil;
|
||||
vfs_extattrctl :nil;
|
||||
vfs_sysctl :nil;
|
||||
vfs_susp_clean :nil;
|
||||
vfs_reclaim_lowervp:@notify_lowervp_vfs_dummy;
|
||||
vfs_unlink_lowervp :@notify_lowervp_vfs_dummy
|
||||
);
|
||||
|
||||
{
|
||||
* Notify upper mounts about reclaimed or unlinked vnode.
|
||||
}
|
||||
procedure vfs_notify_upper(vp:p_vnode;event:Integer);
|
||||
label
|
||||
unlock;
|
||||
var
|
||||
mp,ump,mmp:p_mount;
|
||||
begin
|
||||
mp:=vp^.v_mount;
|
||||
if (mp=nil) then
|
||||
Exit;
|
||||
|
||||
MNT_ILOCK(mp);
|
||||
if TAILQ_EMPTY(@mp^.mnt_uppers) then
|
||||
goto unlock;
|
||||
MNT_IUNLOCK(mp);
|
||||
mmp:=AllocMem(SizeOf(t_mount));
|
||||
mmp^.mnt_op:=@vgonel_vfsops;
|
||||
mmp^.mnt_kern_flag:=mmp^.mnt_kern_flag or MNTK_MARKER;
|
||||
MNT_ILOCK(mp);
|
||||
mp^.mnt_kern_flag:=mmp^.mnt_kern_flag or MNTK_VGONE_UPPER;
|
||||
|
||||
ump:=TAILQ_FIRST(@mp^.mnt_uppers);
|
||||
while (ump<>nil) do
|
||||
begin
|
||||
if ((ump^.mnt_kern_flag and MNTK_MARKER)<>0) then
|
||||
begin
|
||||
ump:=TAILQ_NEXT(ump,@ump^.mnt_upper_link);
|
||||
continue;
|
||||
end;
|
||||
TAILQ_INSERT_AFTER(@mp^.mnt_uppers, ump, mmp,@mmp^.mnt_upper_link);
|
||||
MNT_IUNLOCK(mp);
|
||||
case event of
|
||||
VFS_NOTIFY_UPPER_RECLAIM:
|
||||
VFS_RECLAIM_LOWERVP(ump, vp);
|
||||
VFS_NOTIFY_UPPER_UNLINK:
|
||||
VFS_UNLINK_LOWERVP(ump, vp);
|
||||
else
|
||||
Assert(false, 'invalid event');
|
||||
end;
|
||||
MNT_ILOCK(mp);
|
||||
ump:=TAILQ_NEXT(mmp,@mmp^.mnt_upper_link);
|
||||
TAILQ_REMOVE(@mp^.mnt_uppers, mmp,@mmp^.mnt_upper_link);
|
||||
end;
|
||||
FreeMem(mmp);
|
||||
mp^.mnt_kern_flag:=mp^.mnt_kern_flag and (not MNTK_VGONE_UPPER);
|
||||
if ((mp^.mnt_kern_flag and MNTK_VGONE_WAITER)<>0) then
|
||||
begin
|
||||
mp^.mnt_kern_flag:=mp^.mnt_kern_flag and (not MNTK_VGONE_WAITER);
|
||||
wakeup(@mp^.mnt_uppers);
|
||||
end;
|
||||
unlock:
|
||||
MNT_IUNLOCK(mp);
|
||||
end;
|
||||
|
||||
{
|
||||
* vgone, with the vp interlock held.
|
||||
}
|
||||
|
@ -2540,7 +2467,6 @@ begin
|
|||
active:=vp^.v_usecount;
|
||||
oweinact:=(vp^.v_iflag and VI_OWEINACT);
|
||||
VI_UNLOCK(vp);
|
||||
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_RECLAIM);
|
||||
|
||||
{
|
||||
* Clean out any buffers associated with the vnode.
|
||||
|
@ -3074,6 +3000,7 @@ end;
|
|||
|
||||
procedure vfs_badlock(msg,str:PChar;vp:p_vnode);
|
||||
begin
|
||||
Writeln(msg,' ',str);
|
||||
Assert(false,RawByteString(msg)+' '+RawByteString(str));
|
||||
end;
|
||||
|
||||
|
@ -3573,8 +3500,12 @@ begin
|
|||
mp:=vp^.v_mount;
|
||||
VFS_ASSERT_GIANT(mp);
|
||||
ASSERT_VOP_LOCKED(vp,'vfs_mark_atime');
|
||||
if (mp<>nil) and ((mp^.mnt_flag and (MNT_NOATIME or MNT_RDONLY))=0) then
|
||||
|
||||
if (mp<>nil) then
|
||||
if ((mp^.mnt_flag and (MNT_NOATIME or MNT_RDONLY))=0) then
|
||||
begin
|
||||
VOP_MARKATIME(vp);
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -3642,9 +3573,11 @@ begin
|
|||
MNT_ILOCK(mp);
|
||||
Assert(mvp^^.v_mount=mp, 'marker vnode mount list mismatch');
|
||||
vp:=TAILQ_NEXT(mvp^,@mvp^^.v_nmntvnodes);
|
||||
while (vp<>nil) and
|
||||
((vp^.v_type=VMARKER) or ((vp^.v_iflag and VI_DOOMED)<>0)) do
|
||||
while (vp<>nil) do
|
||||
begin
|
||||
if not ((vp^.v_type=VMARKER) or ((vp^.v_iflag and VI_DOOMED)<>0)) then Break;
|
||||
vp:=TAILQ_NEXT(vp,@vp^.v_nmntvnodes);
|
||||
end;
|
||||
|
||||
{ Check if we are done }
|
||||
if (vp=nil) then
|
||||
|
|
|
@ -18,7 +18,7 @@ uses
|
|||
vfilio,
|
||||
vdisk,
|
||||
vfs_mount,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfs_vnops,
|
||||
vfs_subr,
|
||||
vfs_lookup;
|
||||
|
@ -100,8 +100,7 @@ uses
|
|||
kern_synch,
|
||||
kern_descrip,
|
||||
vnode_if,
|
||||
sys_capability,
|
||||
vm_object;
|
||||
sys_capability;
|
||||
|
||||
{
|
||||
* Sync each mounted filesystem.
|
||||
|
@ -1395,7 +1394,6 @@ begin
|
|||
//if (error)
|
||||
// goto _out;
|
||||
|
||||
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
|
||||
error:=VOP_REMOVE(nd.ni_dvp, vp, @nd.ni_cnd);
|
||||
|
||||
_out:
|
||||
|
@ -2694,7 +2692,6 @@ restart:
|
|||
Exit(error);
|
||||
goto restart;
|
||||
end;
|
||||
vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK);
|
||||
error:=VOP_RMDIR(nd.ni_dvp, nd.ni_vp, @nd.ni_cnd);
|
||||
vn_finished_write(mp);
|
||||
_out:
|
||||
|
|
|
@ -13,7 +13,7 @@ uses
|
|||
vuio,
|
||||
vmparam,
|
||||
vfilio,
|
||||
vfs_vnode;
|
||||
vnode;
|
||||
|
||||
function vn_lock(vp:p_vnode;flags:Integer):Integer;
|
||||
|
||||
|
@ -414,13 +414,15 @@ var
|
|||
mp:p_mount;
|
||||
error, lock_flags:Integer;
|
||||
begin
|
||||
lock_flags:=LK_EXCLUSIVE;
|
||||
|
||||
if (vp^.v_type<>VFIFO) and
|
||||
((flags and FWRITE)=0) and
|
||||
(vp^.v_mount<>nil) and
|
||||
((p_mount(vp^.v_mount)^.mnt_kern_flag and MNTK_EXTENDED_SHARED)<>0) then
|
||||
lock_flags:=LK_SHARED
|
||||
else
|
||||
lock_flags:=LK_EXCLUSIVE;
|
||||
(vp^.v_mount<>nil) then
|
||||
if ((p_mount(vp^.v_mount)^.mnt_kern_flag and MNTK_EXTENDED_SHARED)<>0) then
|
||||
begin
|
||||
lock_flags:=LK_SHARED;
|
||||
end;
|
||||
|
||||
VFS_ASSERT_GIANT(vp^.v_mount);
|
||||
|
||||
|
@ -714,8 +716,8 @@ begin
|
|||
__end:=uio^.uio_offset - 1;
|
||||
mtxp:=mtx_pool_find(mtxpool_sleep, fp);
|
||||
mtx_lock(mtxp^);
|
||||
if (fp^.f_advice<>nil) and
|
||||
(p_fadvise_info(fp^.f_advice)^.fa_advice=POSIX_FADV_NOREUSE) then
|
||||
if (fp^.f_advice<>nil) then
|
||||
if (p_fadvise_info(fp^.f_advice)^.fa_advice=POSIX_FADV_NOREUSE) then
|
||||
begin
|
||||
if (start<>0) and (p_fadvise_info(fp^.f_advice)^.fa_prevend + 1=start) then
|
||||
begin
|
||||
|
@ -761,15 +763,26 @@ begin
|
|||
// bwillwrite();
|
||||
ioflag:=IO_UNIT;
|
||||
if (vp^.v_type=VREG) and ((fp^.f_flag and O_APPEND)<>0) then
|
||||
begin
|
||||
ioflag:=ioflag or IO_APPEND;
|
||||
end;
|
||||
if ((fp^.f_flag and FNONBLOCK)<>0) then
|
||||
begin
|
||||
ioflag:=ioflag or IO_NDELAY;
|
||||
end;
|
||||
if ((fp^.f_flag and O_DIRECT)<>0) then
|
||||
begin
|
||||
ioflag:=ioflag or IO_DIRECT;
|
||||
if ((fp^.f_flag and O_FSYNC)<>0) or
|
||||
((vp^.v_mount<>nil) and
|
||||
((p_mount(vp^.v_mount)^.mnt_flag and MNT_SYNCHRONOUS)<>0)) then
|
||||
end;
|
||||
if ((fp^.f_flag and O_FSYNC)<>0) then
|
||||
begin
|
||||
ioflag:=ioflag or IO_SYNC;
|
||||
end;
|
||||
if (vp^.v_mount<>nil) then
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_SYNCHRONOUS)<>0) then
|
||||
begin
|
||||
ioflag:=ioflag or IO_SYNC;
|
||||
end;
|
||||
mp:=nil;
|
||||
if (vp^.v_type<>VCHR) then
|
||||
begin
|
||||
|
@ -817,8 +830,8 @@ begin
|
|||
__end:=uio^.uio_offset - 1;
|
||||
mtxp:=mtx_pool_find(mtxpool_sleep, fp);
|
||||
mtx_lock(mtxp^);
|
||||
if (fp^.f_advice<>nil) and
|
||||
(p_fadvise_info(fp^.f_advice)^.fa_advice=POSIX_FADV_NOREUSE) then
|
||||
if (fp^.f_advice<>nil) then
|
||||
if (p_fadvise_info(fp^.f_advice)^.fa_advice=POSIX_FADV_NOREUSE) then
|
||||
begin
|
||||
if (start<>0) and (p_fadvise_info(fp^.f_advice)^.fa_prevend + 1=start) then
|
||||
begin
|
||||
|
@ -872,10 +885,15 @@ begin
|
|||
foffset_lock_uio(fp, uio, flags);
|
||||
|
||||
mp:=vp^.v_mount;
|
||||
if (mp<>nil) then
|
||||
if ((mp^.mnt_kern_flag and MNTK_NO_IOPF)=0) then
|
||||
begin
|
||||
error:=doio(fp, uio, flags or FOF_OFFSET);
|
||||
goto out_last;
|
||||
end;
|
||||
|
||||
if (uio^.uio_segflg<>UIO_USERSPACE) or
|
||||
(vp^.v_type<>VREG) or
|
||||
((mp<>nil) and
|
||||
((mp^.mnt_kern_flag and MNTK_NO_IOPF)=0)) or
|
||||
{(not vn_io_fault_enable)} false then
|
||||
begin
|
||||
error:=doio(fp, uio, flags or FOF_OFFSET);
|
||||
|
|
|
@ -11,7 +11,7 @@ uses
|
|||
kern_mtx,
|
||||
kern_synch,
|
||||
kern_sig,
|
||||
vfs_vnode;
|
||||
vnode;
|
||||
|
||||
const
|
||||
DFLTPHYS=(64*1024);
|
||||
|
@ -240,7 +240,7 @@ type
|
|||
vfs_cmount_t =function (ma,data:Pointer;flags:QWORD):Integer;
|
||||
vfs_unmount_t =function (mp:p_mount;mntflags:Integer):Integer;
|
||||
vfs_root_t =function (mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
|
||||
vfs_quotactl_t =function (mp:p_mount;cmds:Integer;uid:Integer;arg:Pointer):Integer;
|
||||
vfs_quotactl_t =function (mp:p_mount;cmds,uid:Integer;arg:Pointer):Integer;
|
||||
vfs_statfs_t =function (mp:p_mount;sbp:p_statfs):Integer;
|
||||
vfs_sync_t =function (mp:p_mount;waitfor:Integer):Integer;
|
||||
vfs_vget_t =function (mp:p_mount;ino:DWORD;flags:Integer;vpp:pp_vnode):Integer;
|
||||
|
@ -256,23 +256,21 @@ type
|
|||
|
||||
p_vfsops=^vfsops;
|
||||
vfsops=packed record
|
||||
vfs_mount :vfs_mount_t ;
|
||||
vfs_cmount :vfs_cmount_t ;
|
||||
vfs_unmount :vfs_unmount_t ;
|
||||
vfs_root :vfs_root_t ;
|
||||
vfs_quotactl :vfs_quotactl_t ;
|
||||
vfs_statfs :vfs_statfs_t ;
|
||||
vfs_sync :vfs_sync_t ;
|
||||
vfs_vget :vfs_vget_t ;
|
||||
vfs_fhtovp :vfs_fhtovp_t ;
|
||||
vfs_checkexp :vfs_checkexp_t ;
|
||||
vfs_init :vfs_init_t ;
|
||||
vfs_uninit :vfs_uninit_t ;
|
||||
vfs_extattrctl :vfs_extattrctl_t ;
|
||||
vfs_sysctl :vfs_sysctl_t ;
|
||||
vfs_susp_clean :vfs_susp_clean_t ;
|
||||
vfs_reclaim_lowervp:vfs_notify_lowervp_t;
|
||||
vfs_unlink_lowervp :vfs_notify_lowervp_t;
|
||||
vfs_mount :vfs_mount_t ;
|
||||
vfs_cmount :vfs_cmount_t ;
|
||||
vfs_unmount :vfs_unmount_t ;
|
||||
vfs_root :vfs_root_t ;
|
||||
vfs_quotactl :vfs_quotactl_t ;
|
||||
vfs_statfs :vfs_statfs_t ;
|
||||
vfs_sync :vfs_sync_t ;
|
||||
vfs_vget :vfs_vget_t ;
|
||||
vfs_fhtovp :vfs_fhtovp_t ;
|
||||
vfs_checkexp :vfs_checkexp_t ;
|
||||
vfs_init :vfs_init_t ;
|
||||
vfs_uninit :vfs_uninit_t ;
|
||||
vfs_extattrctl:vfs_extattrctl_t;
|
||||
vfs_sysctl :vfs_sysctl_t ;
|
||||
vfs_susp_clean:vfs_susp_clean_t;
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -286,7 +284,7 @@ type
|
|||
|
||||
vfsconf=packed record
|
||||
vfc_version :DWORD ; // ABI version number
|
||||
vfc_name :array[0..MFSNAMELEN-1] of Char; // filesystem type name
|
||||
vfc_name :array[0..MFSNAMELEN-1+4] of Char; // filesystem type name
|
||||
vfc_vfsops :p_vfsops ; // filesystem operations vector
|
||||
vfc_typenum :Integer ; // historic filesystem type number
|
||||
vfc_refcount:Integer ; // number mounted of this type
|
||||
|
@ -397,12 +395,12 @@ function MNT_MTX(mp:p_mount):p_mtx; inline;
|
|||
procedure MNT_REF(mp:p_mount); inline;
|
||||
procedure MNT_REL(mp:p_mount); inline;
|
||||
|
||||
function VFS_NEEDSGIANT(mp:p_mount):Boolean; inline;
|
||||
function VFS_NEEDSGIANT(mp:p_mount):Boolean;
|
||||
function VFS_LOCK_GIANT(mp:p_mount):Integer;
|
||||
procedure VFS_UNLOCK_GIANT(locked:Integer);
|
||||
procedure VFS_ASSERT_GIANT(mp:p_mount);
|
||||
|
||||
function VFS_PROLOGUE(mp:p_mount):Boolean; inline;
|
||||
function VFS_PROLOGUE(mp:p_mount):Boolean;
|
||||
procedure VFS_EPILOGUE(_enable_stops:Boolean); inline;
|
||||
|
||||
function VFS_MOUNT(mp:p_mount):Integer;
|
||||
|
@ -411,8 +409,9 @@ function VFS_ROOT(mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
|
|||
function VFS_STATFS(mp:p_mount;sbp:p_statfs):Integer;
|
||||
function VFS_SYNC(mp:p_mount;WAIT:Integer):Integer;
|
||||
function VFS_VGET(mp:p_mount;ino:QWORD;flags:Integer;vpp:pp_vnode):Integer;
|
||||
procedure VFS_RECLAIM_LOWERVP(mp:p_mount;vp:p_vnode);
|
||||
procedure VFS_UNLINK_LOWERVP(mp:p_mount;vp:p_vnode);
|
||||
function VFS_QUOTACTL(mp:p_mount;c,u:Integer;a:Pointer):Integer;
|
||||
function VFS_FHTOVP(mp:p_mount;fidp:p_fid;flags:Integer;vpp:pp_vnode):Integer;
|
||||
function VFS_EXTATTRCTL(mp:p_mount;c:Integer;fn:p_vnode;ns:Integer;n:PChar):Integer;
|
||||
procedure VFS_KNOTE_LOCKED(vp:p_vnode;hint:Integer);
|
||||
procedure VFS_KNOTE_UNLOCKED(vp:p_vnode;hint:Integer);
|
||||
|
||||
|
@ -464,9 +463,15 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function VFS_NEEDSGIANT(mp:p_mount):Boolean; inline;
|
||||
function VFS_NEEDSGIANT(mp:p_mount):Boolean;
|
||||
begin
|
||||
Result:=(mp<>nil) and ((mp^.mnt_kern_flag and MNTK_MPSAFE)=0) ;
|
||||
if (mp<>nil) then
|
||||
begin
|
||||
Result:=((mp^.mnt_kern_flag and MNTK_MPSAFE)=0);
|
||||
end else
|
||||
begin
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function VFS_LOCK_GIANT(mp:p_mount):Integer;
|
||||
|
@ -491,9 +496,15 @@ begin
|
|||
mtx_assert(VFS_Giant);
|
||||
end;
|
||||
|
||||
function VFS_PROLOGUE(mp:p_mount):Boolean; inline;
|
||||
function VFS_PROLOGUE(mp:p_mount):Boolean;
|
||||
begin
|
||||
Result:=(mp<>nil) and ((mp^.mnt_vfc^.vfc_flags and VFCF_SBDRY)<>0) and (sigdeferstop<>0);
|
||||
if (mp<>nil) then
|
||||
begin
|
||||
Result:=((mp^.mnt_vfc^.vfc_flags and VFCF_SBDRY)<>0) and (sigdeferstop<>0);
|
||||
end else
|
||||
begin
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure VFS_EPILOGUE(_enable_stops:Boolean); inline;
|
||||
|
@ -559,28 +570,31 @@ begin
|
|||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
|
||||
procedure VFS_RECLAIM_LOWERVP(mp:p_mount;vp:p_vnode);
|
||||
function VFS_QUOTACTL(mp:p_mount;c,u:Integer;a:Pointer):Integer;
|
||||
var
|
||||
_enable_stops:Boolean;
|
||||
begin
|
||||
if (mp^.mnt_op^.vfs_reclaim_lowervp<>nil) then
|
||||
begin
|
||||
_enable_stops:=VFS_PROLOGUE(MP);
|
||||
mp^.mnt_op^.vfs_reclaim_lowervp(mp,vp);
|
||||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
_enable_stops:=VFS_PROLOGUE(MP);
|
||||
Result:=mp^.mnt_op^.vfs_quotactl(mp,c,u,a);
|
||||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
|
||||
procedure VFS_UNLINK_LOWERVP(mp:p_mount;vp:p_vnode);
|
||||
function VFS_FHTOVP(mp:p_mount;fidp:p_fid;flags:Integer;vpp:pp_vnode):Integer;
|
||||
var
|
||||
_enable_stops:Boolean;
|
||||
begin
|
||||
if (mp^.mnt_op^.vfs_unlink_lowervp<>nil) then
|
||||
begin
|
||||
_enable_stops:=VFS_PROLOGUE(MP);
|
||||
mp^.mnt_op^.vfs_unlink_lowervp(mp,vp);
|
||||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
_enable_stops:=VFS_PROLOGUE(MP);
|
||||
Result:=mp^.mnt_op^.vfs_fhtovp(mp,fidp,flags,vpp);
|
||||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
|
||||
function VFS_EXTATTRCTL(mp:p_mount;c:Integer;fn:p_vnode;ns:Integer;n:PChar):Integer;
|
||||
var
|
||||
_enable_stops:Boolean;
|
||||
begin
|
||||
_enable_stops:=VFS_PROLOGUE(MP);
|
||||
Result:=mp^.mnt_op^.vfs_extattrctl(mp,c,fn,ns,n);
|
||||
VFS_EPILOGUE(_enable_stops);
|
||||
end;
|
||||
|
||||
procedure VFS_KNOTE_LOCKED(vp:p_vnode;hint:Integer);
|
||||
|
|
|
@ -9,7 +9,7 @@ uses
|
|||
vcapability,
|
||||
vfcntl,
|
||||
vuio,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
kern_thr;
|
||||
|
||||
const
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
unit vfs_vnode;
|
||||
unit vnode;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
@ -85,7 +85,7 @@ const
|
|||
VSTAT_PERMS =VREAD_ATTRIBUTES or VREAD_ACL;
|
||||
|
||||
//Permissions that allow to change the state of the file in any way.
|
||||
VMODIFY_PERMS =VWRITE or VAPPEND or VADMIN_PERMS or VDELETE_CHILD or VDELETE;
|
||||
VMODIFY_PERMS =VWRITE or VAPPEND or VADMIN_PERMS or VDELETE_CHILD or VDELETE;
|
||||
|
||||
// vn_open_flags
|
||||
VN_OPEN_NOAUDIT=$00000001;
|
||||
|
@ -116,10 +116,51 @@ const
|
|||
DFLTPHYS =(64 * 1024);
|
||||
MAXPHYS =(128 * 1024);
|
||||
|
||||
//Flags for vdesc_flags:
|
||||
VDESC_MAX_VPS=16;
|
||||
// Low order 16 flag bits are reserved for willrele flags for vp arguments.
|
||||
VDESC_VP0_WILLRELE=$0001;
|
||||
VDESC_VP1_WILLRELE=$0002;
|
||||
VDESC_VP2_WILLRELE=$0004;
|
||||
VDESC_VP3_WILLRELE=$0008;
|
||||
VDESC_NOMAP_VPP =$0100;
|
||||
VDESC_VPP_WILLRELE=$0200;
|
||||
|
||||
{
|
||||
* VDESC_NO_OFFSET is used to identify the end of the offset list
|
||||
* and in places where no such field exists.
|
||||
}
|
||||
VDESC_NO_OFFSET=-1;
|
||||
|
||||
type
|
||||
p_accmode_t=^accmode_t;
|
||||
accmode_t=Integer;
|
||||
|
||||
{ This structure describes the vnode operation taking place. }
|
||||
p_vnodeop_desc=^t_vnodeop_desc;
|
||||
t_vnodeop_desc=record
|
||||
vdesc_name :PChar; { a readable name for debugging }
|
||||
vdesc_call :Pointer; { Function to call }
|
||||
|
||||
{
|
||||
* These ops are used by bypass routines to map and locate arguments.
|
||||
* Creds and procs are not needed in bypass routines, but sometimes
|
||||
* they are useful to (for example) transport layers.
|
||||
* Nameidata is useful because it has a cred in it.
|
||||
}
|
||||
vdesc_vp_offsets :PByte; { list ended by VDESC_NO_OFFSET }
|
||||
vdesc_flags :Integer; { VDESC_* flags }
|
||||
vdesc_vpp_offset :Integer; { return vpp location }
|
||||
end;
|
||||
|
||||
p_vop_generic_args=^t_vop_generic_args;
|
||||
t_vop_generic_args=record
|
||||
a_desc:p_vnodeop_desc;
|
||||
//other random data follows, presumably
|
||||
end;
|
||||
|
||||
vop_bypass_t=function(ap:Pointer):Integer;
|
||||
|
||||
pp_vnode=^p_vnode;
|
||||
p_vnode=^t_vnode;
|
||||
|
||||
|
@ -262,12 +303,15 @@ type
|
|||
va_vaflags :DWORD;
|
||||
end;
|
||||
|
||||
function VOPARG_OFFSETTO(s_offset:Integer;struct_p:Pointer):Pointer;
|
||||
function VCALL(c:Pointer):Integer;
|
||||
|
||||
procedure VI_LOCK(vp:p_vnode);
|
||||
function VI_TRYLOCK(vp:p_vnode):Boolean;
|
||||
procedure VI_UNLOCK(vp:p_vnode);
|
||||
function VI_MTX(vp:p_vnode):p_mtx; inline;
|
||||
|
||||
function IGNORE_LOCK(vp:p_vnode):Boolean; inline;
|
||||
function IGNORE_LOCK(vp:p_vnode):Boolean;
|
||||
|
||||
procedure vn_rangelock_unlock(vp:p_vnode;cookie:Pointer);
|
||||
procedure vn_rangelock_unlock_range(vp:p_vnode;cookie:Pointer;start,__end:Int64);
|
||||
|
@ -279,6 +323,68 @@ var
|
|||
|
||||
implementation
|
||||
|
||||
uses
|
||||
vmount;
|
||||
|
||||
function VOPARG_OFFSETTO(s_offset:Integer;struct_p:Pointer):Pointer;
|
||||
begin
|
||||
Result:=struct_p+s_offset;
|
||||
end;
|
||||
|
||||
function get_vp_cb(vp:p_vnode;offset:Pointer):Pointer; inline;
|
||||
var
|
||||
v:p_vop_vector;
|
||||
p:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (vp=nil) then Exit;
|
||||
v:=vp^.v_op;
|
||||
while (v<>nil) do
|
||||
begin
|
||||
p:=PPointer(Pointer(v)+ptrint(offset))^;
|
||||
if (p<>nil) then
|
||||
begin
|
||||
Exit(p);
|
||||
end;
|
||||
p:=v^.vop_bypass;
|
||||
if (p<>nil) then
|
||||
begin
|
||||
Exit(p);
|
||||
end;
|
||||
v:=v^.vop_default;
|
||||
end;
|
||||
end;
|
||||
|
||||
function vcall_panic:Integer; inline;
|
||||
begin
|
||||
Assert(false,'filesystem goof: vcall_panic');
|
||||
Exit(2);
|
||||
end;
|
||||
|
||||
type
|
||||
p_vop_vcall_args=^t_vop_vcall_args;
|
||||
t_vop_vcall_args=record
|
||||
a_desc:p_vnodeop_desc;
|
||||
a_vp :p_vnode;
|
||||
end;
|
||||
|
||||
function VCALL(c:Pointer):Integer;
|
||||
var
|
||||
ap:p_vop_vcall_args;
|
||||
s:Boolean;
|
||||
begin
|
||||
if (c=nil) then Exit(vcall_panic);
|
||||
ap:=c;
|
||||
if (ap^.a_desc=nil) then Exit(vcall_panic);
|
||||
if (ap^.a_vp=nil) then Exit(vcall_panic);
|
||||
if (ap^.a_desc^.vdesc_call=nil) then Exit(vcall_panic);
|
||||
c:=get_vp_cb(ap^.a_vp,ap^.a_desc^.vdesc_call);
|
||||
Assert(c<>nil,'VCALL');
|
||||
s:=VFS_PROLOGUE(ap^.a_vp^.v_mount);
|
||||
Result:=vop_bypass_t(c)(ap);
|
||||
VFS_EPILOGUE(s);
|
||||
end;
|
||||
|
||||
procedure VI_LOCK(vp:p_vnode);
|
||||
begin
|
||||
mtx_lock(vp^.v_interlock);
|
||||
|
@ -299,9 +405,10 @@ begin
|
|||
Result:=@vp^.v_interlock;
|
||||
end;
|
||||
|
||||
function IGNORE_LOCK(vp:p_vnode):Boolean; inline;
|
||||
function IGNORE_LOCK(vp:p_vnode):Boolean;
|
||||
begin
|
||||
Result:=(vp=nil) or (vp^.v_type=VCHR) or (vp^.v_type=VBAD);
|
||||
if (vp=nil) then Exit(True);
|
||||
Result:=(vp^.v_type=VCHR) or (vp^.v_type=VBAD);
|
||||
end;
|
||||
|
||||
procedure vn_rangelock_unlock(vp:p_vnode;cookie:Pointer);
|
2167
sys/vfs/vnode_if.pas
2167
sys/vfs/vnode_if.pas
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@ uses
|
|||
vuio,
|
||||
vfile,
|
||||
vcapability,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfcntl,
|
||||
vfilio,
|
||||
vfiledesc,
|
||||
|
@ -1134,7 +1134,7 @@ begin
|
|||
continue;
|
||||
end;
|
||||
fp:=fget_unlocked(fd^.fd);
|
||||
if (fp=nil) or (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0) then
|
||||
if (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0) then
|
||||
begin
|
||||
if (fp<>nil) then
|
||||
fdrop(fp);
|
||||
|
@ -1208,7 +1208,7 @@ begin
|
|||
end else
|
||||
begin
|
||||
fp:=fget_unlocked(fds^.fd);
|
||||
if ((fp=nil) or (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0)) then
|
||||
if (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0) then
|
||||
begin
|
||||
fds^.revents:=POLLNVAL;
|
||||
Inc(n);
|
||||
|
|
|
@ -482,10 +482,16 @@ end;
|
|||
procedure vm_map_entry_set_max_free(entry:vm_map_entry_t);
|
||||
begin
|
||||
entry^.max_free:=entry^.adj_free;
|
||||
if (entry^.left<>nil) and (entry^.left^.max_free>entry^.max_free) then
|
||||
if (entry^.left<>nil) then
|
||||
if (entry^.left^.max_free>entry^.max_free) then
|
||||
begin
|
||||
entry^.max_free:=entry^.left^.max_free;
|
||||
if (entry^.right<>nil) and (entry^.right^.max_free>entry^.max_free) then
|
||||
end;
|
||||
if (entry^.right<>nil) then
|
||||
if (entry^.right^.max_free>entry^.max_free) then
|
||||
begin
|
||||
entry^.max_free:=entry^.right^.max_free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
|
@ -999,6 +1005,8 @@ function vm_map_findspace(map :vm_map_t;
|
|||
start :vm_offset_t;
|
||||
length:vm_size_t;
|
||||
addr :p_vm_offset_t):Integer;
|
||||
label
|
||||
_nxt;
|
||||
var
|
||||
entry:vm_map_entry_t;
|
||||
st:vm_offset_t;
|
||||
|
@ -1052,7 +1060,11 @@ begin
|
|||
|
||||
{ With max_free, can immediately tell if no solution. }
|
||||
entry:=map^.root^.right;
|
||||
if (entry=nil) or (length>entry^.max_free) then
|
||||
|
||||
if (entry=nil) then
|
||||
Exit(1);
|
||||
|
||||
if (length>entry^.max_free) then
|
||||
Exit(1);
|
||||
|
||||
{
|
||||
|
@ -1062,16 +1074,20 @@ begin
|
|||
}
|
||||
while (entry<>nil) do
|
||||
begin
|
||||
if (entry^.left<>nil) and (entry^.left^.max_free>=length) then
|
||||
if (entry^.left<>nil) then
|
||||
begin
|
||||
if not (entry^.left^.max_free>=length) then goto _nxt;
|
||||
entry:=entry^.left;
|
||||
end else
|
||||
if (entry^.adj_free>=length) then
|
||||
begin
|
||||
addr^:=entry^.__end;
|
||||
Exit(0);
|
||||
end else
|
||||
entry:=entry^.right;
|
||||
_nxt:
|
||||
if (entry^.adj_free>=length) then
|
||||
begin
|
||||
addr^:=entry^.__end;
|
||||
Exit(0);
|
||||
end else
|
||||
entry:=entry^.right;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Can't get here, so panic if we do. }
|
||||
|
@ -1124,11 +1140,16 @@ label
|
|||
var
|
||||
alignment,initial_addr,start:vm_offset_t;
|
||||
begin
|
||||
if (find_space=VMFS_OPTIMAL_SPACE) and
|
||||
((_object=nil) or
|
||||
((_object^.flags and OBJ_COLORED)=0)) then
|
||||
if (find_space=VMFS_OPTIMAL_SPACE) then
|
||||
begin
|
||||
find_space:=VMFS_ANY_SPACE;
|
||||
if (_object=nil) then
|
||||
begin
|
||||
find_space:=VMFS_ANY_SPACE;
|
||||
end else
|
||||
if ((_object^.flags and OBJ_COLORED)=0) then
|
||||
begin
|
||||
find_space:=VMFS_ANY_SPACE;
|
||||
end;
|
||||
end;
|
||||
if ((find_space shr 8)<>0) then
|
||||
begin
|
||||
|
@ -2123,6 +2144,7 @@ end;
|
|||
}
|
||||
function vm_map_growstack(addr:vm_offset_t):Integer;
|
||||
label
|
||||
_or,
|
||||
_out;
|
||||
var
|
||||
next_entry, prev_entry:vm_map_entry_t;
|
||||
|
@ -2340,12 +2362,15 @@ begin
|
|||
|
||||
grow_amount:=addr - stack_entry^.__end;
|
||||
{ Grow the underlying object if applicable. }
|
||||
if ((stack_entry^._object=nil) or
|
||||
vm_object_coalesce(stack_entry^._object,
|
||||
stack_entry^.offset,
|
||||
vm_size_t(stack_entry^.__end - stack_entry^.start),
|
||||
vm_size_t(grow_amount), false)) then
|
||||
|
||||
if (stack_entry^._object=nil) then goto _or;
|
||||
|
||||
if vm_object_coalesce(stack_entry^._object,
|
||||
stack_entry^.offset,
|
||||
vm_size_t(stack_entry^.__end - stack_entry^.start),
|
||||
vm_size_t(grow_amount), false) then
|
||||
begin
|
||||
_or:
|
||||
map^.size:=map^.size+(addr - stack_entry^.__end);
|
||||
{ Update the current entry. }
|
||||
stack_entry^.__end:=addr;
|
||||
|
|
|
@ -45,7 +45,7 @@ uses
|
|||
vstat,
|
||||
vfile,
|
||||
vfcntl,
|
||||
vfs_vnode,
|
||||
vnode,
|
||||
vfs_subr,
|
||||
vnode_if;
|
||||
|
||||
|
@ -457,10 +457,13 @@ begin
|
|||
|
||||
vp:=fp^.f_vnode;
|
||||
|
||||
if (vp^.v_mount<>nil) and ((p_mount(vp^.v_mount)^.mnt_flag and MNT_NOEXEC)<>0) then
|
||||
maxprot:=VM_PROT_NONE
|
||||
else
|
||||
maxprot:=VM_PROT_EXECUTE;
|
||||
maxprot:=VM_PROT_EXECUTE;
|
||||
|
||||
if (vp^.v_mount<>nil) then
|
||||
if ((p_mount(vp^.v_mount)^.mnt_flag and MNT_NOEXEC)<>0) then
|
||||
begin
|
||||
maxprot:=VM_PROT_NONE;
|
||||
end;
|
||||
|
||||
if ((fp^.f_flag and FREAD)<>0) then
|
||||
begin
|
||||
|
|
|
@ -114,8 +114,11 @@ var
|
|||
superpage_offset:vm_offset_t;
|
||||
begin
|
||||
if (size < NBPDR) then Exit;
|
||||
//if (_object<>nil) and ((_object^.flags and OBJ_COLORED)<>0) then
|
||||
//if (_object<>nil) then
|
||||
//if ((_object^.flags and OBJ_COLORED)<>0) then
|
||||
//begin
|
||||
// offset:=offset+ptoa(_object^.pg_color);
|
||||
//end;
|
||||
superpage_offset:=offset and PDRMASK;
|
||||
if (size - ((NBPDR - superpage_offset) and PDRMASK) < NBPDR) or
|
||||
((addr^ and PDRMASK)=superpage_offset) then
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2021 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#ifndef PM4_IT_OPCODES_H
|
||||
#define PM4_IT_OPCODES_H
|
||||
|
||||
enum IT_OpCodeType {
|
||||
IT_NOP = 0x10,
|
||||
IT_SET_BASE = 0x11,
|
||||
IT_CLEAR_STATE = 0x12,
|
||||
IT_INDEX_BUFFER_SIZE = 0x13,
|
||||
IT_DISPATCH_DIRECT = 0x15,
|
||||
IT_DISPATCH_INDIRECT = 0x16,
|
||||
IT_ATOMIC_GDS = 0x1D,
|
||||
IT_ATOMIC = 0x1E,
|
||||
IT_OCCLUSION_QUERY = 0x1F,
|
||||
IT_SET_PREDICATION = 0x20,
|
||||
IT_REG_RMW = 0x21,
|
||||
IT_COND_EXEC = 0x22,
|
||||
IT_PRED_EXEC = 0x23,
|
||||
IT_DRAW_INDIRECT = 0x24,
|
||||
IT_DRAW_INDEX_INDIRECT = 0x25,
|
||||
IT_INDEX_BASE = 0x26,
|
||||
IT_DRAW_INDEX_2 = 0x27,
|
||||
IT_CONTEXT_CONTROL = 0x28,
|
||||
IT_INDEX_TYPE = 0x2A,
|
||||
IT_DRAW_INDIRECT_MULTI = 0x2C,
|
||||
IT_DRAW_INDEX_AUTO = 0x2D,
|
||||
IT_NUM_INSTANCES = 0x2F,
|
||||
IT_DRAW_INDEX_MULTI_AUTO = 0x30,
|
||||
IT_INDIRECT_BUFFER_CNST = 0x33,
|
||||
IT_STRMOUT_BUFFER_UPDATE = 0x34,
|
||||
IT_DRAW_INDEX_OFFSET_2 = 0x35,
|
||||
IT_WRITE_DATA = 0x37,
|
||||
IT_DRAW_INDEX_INDIRECT_MULTI = 0x38,
|
||||
IT_MEM_SEMAPHORE = 0x39,
|
||||
IT_COPY_DW__SI__CI = 0x3B,
|
||||
IT_WAIT_REG_MEM = 0x3C,
|
||||
IT_INDIRECT_BUFFER = 0x3F,
|
||||
IT_COND_INDIRECT_BUFFER = 0x3F,
|
||||
IT_COPY_DATA = 0x40,
|
||||
IT_CP_DMA = 0x41,
|
||||
IT_PFP_SYNC_ME = 0x42,
|
||||
IT_SURFACE_SYNC = 0x43,
|
||||
IT_COND_WRITE = 0x45,
|
||||
IT_EVENT_WRITE = 0x46,
|
||||
IT_EVENT_WRITE_EOP = 0x47,
|
||||
IT_EVENT_WRITE_EOS = 0x48,
|
||||
IT_PREAMBLE_CNTL = 0x4A,
|
||||
IT_CONTEXT_REG_RMW = 0x51,
|
||||
IT_LOAD_SH_REG = 0x5F,
|
||||
IT_LOAD_CONFIG_REG = 0x60,
|
||||
IT_LOAD_CONTEXT_REG = 0x61,
|
||||
IT_SET_CONFIG_REG = 0x68,
|
||||
IT_SET_CONTEXT_REG = 0x69,
|
||||
IT_SET_CONTEXT_REG_INDIRECT = 0x73,
|
||||
IT_SET_SH_REG = 0x76,
|
||||
IT_SET_SH_REG_OFFSET = 0x77,
|
||||
IT_SCRATCH_RAM_WRITE = 0x7D,
|
||||
IT_SCRATCH_RAM_READ = 0x7E,
|
||||
IT_LOAD_CONST_RAM = 0x80,
|
||||
IT_WRITE_CONST_RAM = 0x81,
|
||||
IT_DUMP_CONST_RAM = 0x83,
|
||||
IT_INCREMENT_CE_COUNTER = 0x84,
|
||||
IT_INCREMENT_DE_COUNTER = 0x85,
|
||||
IT_WAIT_ON_CE_COUNTER = 0x86,
|
||||
IT_WAIT_ON_DE_COUNTER__SI = 0x87,
|
||||
IT_WAIT_ON_DE_COUNTER_DIFF = 0x88,
|
||||
IT_SWITCH_BUFFER = 0x8B,
|
||||
IT_DRAW_PREAMBLE__CI__VI = 0x36,
|
||||
IT_RELEASE_MEM__CI__VI = 0x49,
|
||||
IT_DMA_DATA__CI__VI = 0x50,
|
||||
IT_ACQUIRE_MEM__CI__VI = 0x58,
|
||||
IT_REWIND__CI__VI = 0x59,
|
||||
IT_LOAD_UCONFIG_REG__CI__VI = 0x5E,
|
||||
IT_SET_QUEUE_REG__CI__VI = 0x78,
|
||||
IT_SET_UCONFIG_REG__CI__VI = 0x79,
|
||||
IT_INDEX_ATTRIBUTES_INDIRECT__CI__VI = 0x91,
|
||||
IT_SET_SH_REG_INDEX__CI__VI = 0x9B,
|
||||
IT_SET_RESOURCES__CI__VI = 0xA0,
|
||||
IT_MAP_PROCESS__CI__VI = 0xA1,
|
||||
IT_MAP_QUEUES__CI__VI = 0xA2,
|
||||
IT_UNMAP_QUEUES__CI__VI = 0xA3,
|
||||
IT_QUERY_STATUS__CI__VI = 0xA4,
|
||||
IT_RUN_LIST__CI__VI = 0xA5,
|
||||
IT_LOAD_SH_REG_INDEX__VI = 0x63,
|
||||
IT_LOAD_CONTEXT_REG_INDEX__VI = 0x9F,
|
||||
IT_DUMP_CONST_RAM_OFFSET__VI = 0x9E,
|
||||
};
|
||||
|
||||
#define PM4_TYPE_0 0
|
||||
#define PM4_TYPE_2 2
|
||||
#define PM4_TYPE_3 3
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -181,6 +181,9 @@ var
|
|||
S,Name:RawByteString;
|
||||
|
||||
pre,post:RawByteString;
|
||||
releflags:RawByteString;
|
||||
vpp_offset:RawByteString;
|
||||
rele:ptruint;
|
||||
|
||||
F:THandle;
|
||||
|
||||
|
@ -189,6 +192,7 @@ var
|
|||
state:Integer;
|
||||
|
||||
links,maxlen:SizeUInt;
|
||||
vpnum:Integer;
|
||||
begin
|
||||
EnumList:=TStringList.Create;
|
||||
|
||||
|
@ -258,12 +262,13 @@ begin
|
|||
end;
|
||||
1:begin //value
|
||||
|
||||
rele:=0;
|
||||
repeat
|
||||
case Name of
|
||||
'IN':;
|
||||
'OUT':;
|
||||
'INOUT':;
|
||||
'WILLRELE':;
|
||||
'WILLRELE':rele:=1;
|
||||
'struct':;
|
||||
'const':;
|
||||
else
|
||||
|
@ -304,7 +309,7 @@ begin
|
|||
|
||||
if (Length(S)>Enum.namelen) then Enum.namelen:=Length(S);
|
||||
|
||||
Enum.AddPair(S,Name);
|
||||
Enum.AddPair(S,Name,TObject(rele));
|
||||
Writeln(S,':',Name);
|
||||
end;
|
||||
end;
|
||||
|
@ -315,14 +320,18 @@ begin
|
|||
|
||||
F:=FileCreate(ChangeFileExt(fname,'.pas'));
|
||||
|
||||
S:='unit '+ChangeFileExt(ExtractFileName(fname),'')+';'#13#10#13#10+
|
||||
'interface'#13#10#13#10+
|
||||
'{$mode objfpc}{$H+}'#13#10+
|
||||
'{$CALLING SysV_ABI_CDecl}'#13#10#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
S:='{This file is automatically generated by "vop_generator"}'#13#10;
|
||||
S:=S+#13#10;
|
||||
S:=S+'unit '+ChangeFileExt(ExtractFileName(fname),'')+';'#13#10;
|
||||
S:=S+#13#10;
|
||||
S:=S+'interface'#13#10;
|
||||
S:=S+#13#10;
|
||||
S:=S+'{$mode objfpc}{$H+}'#13#10;
|
||||
S:=S+'{$CALLING SysV_ABI_CDecl}'#13#10;
|
||||
S:=S+#13#10;
|
||||
|
||||
S:='uses'#13#10;
|
||||
S:=S+' vfs_vnode,'#13#10;
|
||||
S:=S+'uses'#13#10;
|
||||
S:=S+' vnode,'#13#10;
|
||||
S:=S+' vnamei,'#13#10;
|
||||
S:=S+' vfile,'#13#10;
|
||||
S:=S+' vuio,'#13#10;
|
||||
|
@ -330,9 +339,8 @@ begin
|
|||
S:=S+' vfcntl,'#13#10;
|
||||
S:=S+' vsocketvar;'#13#10;
|
||||
S:=S+#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
S:='type'#13#10;
|
||||
S:=S+'type'#13#10;
|
||||
S:=S+' PPPtrUint =^PPtrUint;'#13#10;
|
||||
S:=S+' pp_bufobj =Pointer;'#13#10;
|
||||
S:=S+' daddr_t =PtrUint;'#13#10;
|
||||
|
@ -355,21 +363,22 @@ begin
|
|||
Enum:=TEnum(EnumList.Objects[i]);
|
||||
|
||||
S:=' p_'+Enum.name+'_args=^'+Enum.name+'_args;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
S:=' '+Enum.name+'_args=record'#13#10;
|
||||
S:=S+' '+Enum.name+'_args=record'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
if (Length(Enum.name)>maxlen) then maxlen:=Length(Enum.name);
|
||||
|
||||
if Length('gen')>Enum.namelen then Enum.namelen:=Length('gen');
|
||||
|
||||
S:=' a_gen'+Space(Enum.namelen-Length('gen'))+':p_vnodeop_desc;'#13#10;
|
||||
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.Names[x];
|
||||
S:=' a_'+Name+Space(Enum.namelen-Length(Name))+':'+Enum.ValueFromIndex[x]+';'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
S:=S+' a_'+Name+Space(Enum.namelen-Length(Name))+':'+Enum.ValueFromIndex[x]+';'#13#10;
|
||||
end;
|
||||
|
||||
S:=' end;'#13#10#13#10;
|
||||
S:=S+' end;'#13#10#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
|
@ -386,16 +395,16 @@ begin
|
|||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//list
|
||||
For i:=0 to EnumList.Count-1 do
|
||||
begin
|
||||
Enum:=TEnum(EnumList.Objects[i]);
|
||||
//For i:=0 to EnumList.Count-1 do
|
||||
//begin
|
||||
// Enum:=TEnum(EnumList.Objects[i]);
|
||||
//
|
||||
// S:='//'+Enum.name+Space(maxlen-Length(Enum.name))+':Pointer;'#13#10;
|
||||
// FileWrite(F,Pchar(S)^,Length(S));
|
||||
//end;
|
||||
|
||||
S:='//'+Enum.name+Space(maxlen-Length(Enum.name))+':Pointer;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
S:=#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
//S:=#13#10;
|
||||
//FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//functions header
|
||||
For i:=0 to EnumList.Count-1 do
|
||||
|
@ -405,7 +414,7 @@ begin
|
|||
Name:=FixFuncName(Enum.name);
|
||||
Name:=Upcase(Name);
|
||||
|
||||
S:='function '+Name+'(';
|
||||
S:='function '+Name+Space(maxlen-Length(Name))+'(';
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
For x:=0 to Enum.Count-1 do
|
||||
|
@ -423,9 +432,166 @@ begin
|
|||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
S:=#13#10'implementation'#13#10#13#10;
|
||||
//const
|
||||
S:=#13#10'const'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//vp_offsets
|
||||
For i:=0 to EnumList.Count-1 do
|
||||
begin
|
||||
Enum:=TEnum(EnumList.Objects[i]);
|
||||
|
||||
S:=' '+Enum.name+'_vp_offsets'+Space(maxlen-Length(Enum.name))+':array[0..';
|
||||
|
||||
//calc count
|
||||
vpnum:=0;
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.ValueFromIndex[x];
|
||||
if (Name='p_vnode') then
|
||||
begin
|
||||
Inc(vpnum);
|
||||
end;
|
||||
end;
|
||||
Assert(vpnum<>0);
|
||||
|
||||
S:=S+IntToStr(vpnum)+'] of Byte=(';
|
||||
|
||||
//offsets
|
||||
vpnum:=0;
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.ValueFromIndex[x];
|
||||
if (Name='p_vnode') then
|
||||
begin
|
||||
if (vpnum<>0) then
|
||||
begin
|
||||
S:=S+',';
|
||||
end;
|
||||
|
||||
Name:=Enum.Names[x];
|
||||
Name:='a_'+Name;
|
||||
|
||||
S:=S+'Byte(ptrint(@p_'+Enum.name+'_args(nil)^.'+Name+'))';
|
||||
|
||||
Inc(vpnum);
|
||||
end;
|
||||
end;
|
||||
|
||||
S:=S+',Byte(-1));'#13#10;
|
||||
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
S:=#13#10;
|
||||
S:=S+' vop_default_desc:t_vnodeop_desc=('#13#10;
|
||||
S:=S+' vdesc_name :''default'';'#13#10;
|
||||
S:=S+' vdesc_call :nil;'#13#10;
|
||||
S:=S+' vdesc_vp_offsets :nil;'#13#10;
|
||||
S:=S+' vdesc_flags :0;'#13#10;
|
||||
S:=S+' vdesc_vpp_offset :-1;'#13#10;
|
||||
S:=S+' );'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//vnodeop_desc
|
||||
For i:=0 to EnumList.Count-1 do
|
||||
begin
|
||||
Enum:=TEnum(EnumList.Objects[i]);
|
||||
|
||||
//releflags
|
||||
vpnum:=0;
|
||||
releflags:='';
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.ValueFromIndex[x];
|
||||
if (Name='p_vnode') then
|
||||
begin
|
||||
if (Enum.Objects[x]<>nil) then //rele
|
||||
begin
|
||||
if (releflags<>'') then
|
||||
begin
|
||||
releflags:=releflags+' or ';
|
||||
end;
|
||||
releflags:=releflags+'VDESC_VP'+IntToStr(vpnum)+'_WILLRELE';
|
||||
end;
|
||||
Inc(vpnum);
|
||||
end;
|
||||
end;
|
||||
|
||||
//vppwillrele,vpp_offset
|
||||
vpp_offset:='';
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.ValueFromIndex[x];
|
||||
if (Name='pp_vnode') then
|
||||
begin
|
||||
if (vpp_offset='') then
|
||||
begin
|
||||
Name:=Enum.Names[x];
|
||||
Name:='a_'+Name;
|
||||
|
||||
vpp_offset:='Integer(ptrint(@p_'+Enum.name+'_args(nil)^.'+Name+'))';
|
||||
end;
|
||||
|
||||
if (Enum.Objects[x]<>nil) then //rele
|
||||
begin
|
||||
if (releflags<>'') then
|
||||
begin
|
||||
releflags:=releflags+' or ';
|
||||
end;
|
||||
releflags:=releflags+'VDESC_VPP_WILLRELE';
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (releflags='') then releflags:='0';
|
||||
if (vpp_offset='') then vpp_offset:='-1';
|
||||
|
||||
S:=#13#10;
|
||||
S:=S+' '+Enum.name+'_desc:t_vnodeop_desc=('#13#10;
|
||||
S:=S+' vdesc_name :'''+Enum.name+''';'#13#10;
|
||||
S:=S+' vdesc_call :@p_vop_vector(nil)^.'+Enum.name+';'#13#10;
|
||||
S:=S+' vdesc_vp_offsets :@'+Enum.name+'_vp_offsets;'#13#10;
|
||||
S:=S+' vdesc_flags :'+releflags+';'#13#10;
|
||||
S:=S+' vdesc_vpp_offset :'+vpp_offset+';'#13#10;
|
||||
S:=S+' );'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
S:=#13#10;
|
||||
S:=S+'implementation'#13#10;
|
||||
S:=S+#13#10;
|
||||
S:=S+'uses'#13#10;
|
||||
S:=S+' vfs_subr;'#13#10#13#10;
|
||||
S:=S+' errno,'#13#10;
|
||||
S:=S+' vfs_subr;'#13#10;
|
||||
S:=S+#13#10;
|
||||
|
||||
S:=S+'function get_vp_cb(vp:p_vnode;offset:Pointer):Pointer; inline;'#13#10;
|
||||
S:=S+'var'#13#10;
|
||||
S:=S+' v:p_vop_vector;'#13#10;
|
||||
S:=S+' p:Pointer;'#13#10;
|
||||
S:=S+'begin'#13#10;
|
||||
S:=S+' Result:=nil;'#13#10;
|
||||
S:=S+' if (vp=nil) then Exit;'#13#10;
|
||||
S:=S+' v:=vp^.v_op;'#13#10;
|
||||
S:=S+' while (v<>nil) do'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' p:=PPointer(Pointer(v)+ptrint(offset))^;'#13#10;
|
||||
S:=S+' if (p<>nil) then'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' Exit(p);'#13#10;
|
||||
S:=S+' end;'#13#10;
|
||||
S:=S+' p:=v^.vop_bypass;'#13#10;
|
||||
S:=S+' if (p<>nil) then'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' Exit(p);'#13#10;
|
||||
S:=S+' end;'#13#10;
|
||||
S:=S+' v:=v^.vop_default;'#13#10;
|
||||
S:=S+' end;'#13#10;
|
||||
S:=S+'end;'#13#10;
|
||||
S:=S+#13#10;
|
||||
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//functions body
|
||||
|
@ -457,17 +623,15 @@ begin
|
|||
|
||||
//var
|
||||
S:='var'#13#10;
|
||||
S:=S+' v:p_vop_vector;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//var
|
||||
if (Enum.Count>1) then
|
||||
if (Upcase(Enum.name)='VOP_WRITE') then
|
||||
begin
|
||||
S:=' a:'+Enum.name+'_args;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
S:=S+' osize,ooffset:Int64;'#13#10;
|
||||
end;
|
||||
|
||||
S:=' s:Boolean;'#13#10;
|
||||
S:=S+' c:Pointer;'#13#10;
|
||||
S:=S+' a:'+Enum.name+'_args;'#13#10;
|
||||
S:=S+' s:Boolean;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//body
|
||||
|
@ -477,62 +641,51 @@ begin
|
|||
Name:=FixFuncName(Enum.name);
|
||||
Name:=Upcase(Name);
|
||||
|
||||
S:=' v:='+FixFieldName(Enum.Names[0])+'^.v_op;'#13#10;
|
||||
S:=S+' while (v<>nil) do'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' if (v^.'+Enum.name+'<>nil) or (v^.vop_bypass<>nil) then Break;'#13#10;
|
||||
S:=S+' v:=v^.vop_default;'#13#10;
|
||||
S:=S+' end;'#13#10;
|
||||
S:=S+' Assert(v<>nil,'+''''+Name+''''+');'#13#10;
|
||||
S:=' c:=get_vp_cb('+FixFieldName(Enum.Names[0])+','+Enum.name+'_desc.vdesc_call);'#13#10;
|
||||
S:=S+' Assert(c<>nil,'+''''+Name+''''+');'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
if (Enum.Count>1) then
|
||||
begin
|
||||
//set val
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.Names[x];
|
||||
//set val
|
||||
S:=' a.a_gen'+Space(Enum.namelen-Length('gen'))+':=@'+Enum.name+'_desc;'#13#10;
|
||||
|
||||
S:=' a.a_'+Name+Space(Enum.namelen-Length(Name))+':='+FixFieldName(Name)+';'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
For x:=0 to Enum.Count-1 do
|
||||
begin
|
||||
Name:=Enum.Names[x];
|
||||
|
||||
S:=S+' a.a_'+Name+Space(Enum.namelen-Length(Name))+':='+FixFieldName(Name)+';'#13#10;
|
||||
end;
|
||||
|
||||
if (Enum.Count>1) then
|
||||
begin
|
||||
Name:='a';
|
||||
end else
|
||||
begin
|
||||
Name:=FixFieldName(Enum.Names[0]);
|
||||
end;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//pre
|
||||
if (Enum.pre<>'') then
|
||||
begin
|
||||
S:=' '+Enum.pre+'(@'+Name+');'#13#10;
|
||||
S:=' '+Enum.pre+'(@'+'a';
|
||||
if (Upcase(Enum.name)='VOP_WRITE') then
|
||||
begin
|
||||
S:=S+',osize,ooffset';
|
||||
end;
|
||||
S:=S+');'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
S:=' s:=VFS_PROLOGUE('+FixFieldName(Enum.Names[0])+'^.v_mount);'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//call
|
||||
S:=' if (v^.'+Enum.name+'<>nil) then'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' Result:='+Enum.name+'_t(v^.'+Enum.name+')(@'+Name+');'#13#10;
|
||||
S:=S+' end else'#13#10;
|
||||
S:=S+' begin'#13#10;
|
||||
S:=S+' Result:='+Enum.name+'_t(v^.vop_bypass)(@'+Name+');'#13#10;
|
||||
S:=S+' end;'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
S:=S+' Result:='+Enum.name+'_t(c)(@a);'#13#10;
|
||||
|
||||
S:=' VFS_EPILOGUE(s);'#13#10;
|
||||
S:=S+' VFS_EPILOGUE(s);'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
|
||||
//post
|
||||
if (Enum.post<>'') then
|
||||
begin
|
||||
S:=' '+Enum.post+'(@'+Name+',Result);'#13#10;
|
||||
S:=' '+Enum.post+'(@a,Result';
|
||||
if (Upcase(Enum.name)='VOP_WRITE') then
|
||||
begin
|
||||
S:=S+',osize,ooffset';
|
||||
end;
|
||||
S:=S+');'#13#10;
|
||||
FileWrite(F,Pchar(S)^,Length(S));
|
||||
end;
|
||||
|
||||
|
|
Loading…
Reference in New Issue