FPPS4/sys/fs/fdescfs/fdesc_vfsops.pas

216 lines
4.2 KiB
Plaintext

unit fdesc_vfsops;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
vmount,
kern_param,
vfs_mount,
vnode,
fdescfs;
{
* /dev/fd Filesystem
}
function fdesc_cmount(ma,data:Pointer;flags:QWORD):Integer;
function fdesc_mount(mp:p_mount):Integer;
function fdesc_unmount(mp:p_mount;mntflags:Integer):Integer;
function fdesc_root(mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
function fdesc_statfs(mp:p_mount;sbp:p_statfs):Integer;
const
_fdesc_vfsops:vfsops=(
vfs_mount :@fdesc_mount;
vfs_cmount :@fdesc_cmount;
vfs_unmount :@fdesc_unmount;
vfs_root :@fdesc_root;
vfs_quotactl :nil;
vfs_statfs :@fdesc_statfs;
vfs_sync :nil;
vfs_vget :nil;
vfs_fhtovp :nil;
vfs_checkexp :nil;
vfs_init :@fdesc_init;
vfs_uninit :@fdesc_uninit;
vfs_extattrctl :nil;
vfs_sysctl :nil;
vfs_susp_clean :nil;
);
//VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC);
fdescfs_vfsconf:vfsconf=(
vfc_version :VFS_VERSION;
vfc_name :'fdescfs';
vfc_vfsops :@_fdesc_vfsops;
vfc_typenum :-1;
vfc_refcount:0;
vfc_flags :VFCF_SYNTHETIC;
vfc_opts :nil;
vfc_list :(tqe_next:nil;tqe_prev:nil)
);
implementation
uses
errno,
vfiledesc,
vfs_subr,
vnode_if,
kern_mtx,
kern_id,
fdesc_vnops;
function VFSTOFDESC(mp:p_mount):p_fdescmount; inline;
begin
Result:=mp^.mnt_data;
end;
function VTOFDESC(vp:p_vnode):p_fdescnode; inline;
begin
Result:=vp^.v_data;
end;
{
* Compatibility shim for old mount(2) system call.
}
function fdesc_cmount(ma,data:Pointer;flags:QWORD):Integer;
begin
Exit(kernel_nmount(ma, flags));
end;
{
* Mount the per-process file descriptors (/dev/fd)
}
function fdesc_mount(mp:p_mount):Integer;
var
error:Integer;
fmp:p_fdescmount;
rvp:p_vnode;
begin
error:=0;
rvp:=nil;
{
* Update is a no-op
}
if ((mp^.mnt_flag and (MNT_UPDATE or MNT_ROOTFS))<>0) then
Exit(EOPNOTSUPP);
fmp:=AllocMem(sizeof(t_fdescmount)); { XXX }
{
* We need to initialize a few bits of our local mount point struct to
* avoid confusion in allocvp.
}
mp^.mnt_data:=fmp;
fmp^.flags:=0;
error:=fdesc_allocvp(_Froot, -1, FD_ROOT, mp, @rvp);
if (error<>0) then
begin
FreeMem(fmp);
mp^.mnt_data:=nil;
Exit(error);
end;
rvp^.v_type:=VDIR;
rvp^.v_vflag:=rvp^.v_vflag or VV_ROOT;
fmp^.f_root:=rvp;
VOP_UNLOCK(rvp, 0);
{ XXX -- don't mark as local to work around fts() problems }
{mp^.mnt_flag:=mp^.mnt_flag or MNT_LOCAL;}
MNT_ILOCK(mp);
mp^.mnt_kern_flag:=mp^.mnt_kern_flag or MNTK_MPSAFE;
MNT_IUNLOCK(mp);
vfs_getnewfsid(mp);
vfs_mountedfrom(mp, 'fdescfs');
Exit(0);
end;
function fdesc_unmount(mp:p_mount;mntflags:Integer):Integer;
var
fmp:p_fdescmount;
data:Pointer;
error:Integer;
flags:Integer;
begin
flags:=0;
fmp:=p_fdescmount(mp^.mnt_data);
if ((mntflags and MNT_FORCE)<>0) then
begin
{ The hash mutex protects the private mount flags. }
mtx_lock(fdesc_hashmtx);
fmp^.flags:=fmp^.flags or FMNT_UNMOUNTF;
mtx_unlock(fdesc_hashmtx);
flags:=flags or FORCECLOSE;
end;
{
* Clear out buffer cache. I don't think we
* ever get anything cached at this level at the
* moment, but who knows...
*
* There is 1 extra root vnode reference corresponding
* to f_root.
}
error:=vflush(mp, 1, flags);
if (error<>0) then
Exit(error);
{
* Finally, throw away the fdescmount structure. Hold the hashmtx to
* protect the fdescmount structure.
}
mtx_lock(fdesc_hashmtx);
data:=mp^.mnt_data;
mp^.mnt_data:=nil;
mtx_unlock(fdesc_hashmtx);
FreeMem(data); { XXX }
Exit(0);
end;
function fdesc_root(mp:p_mount;flags:Integer;vpp:pp_vnode):Integer;
var
vp:p_vnode;
begin
{
* Exitlocked reference to root.
}
vp:=VFSTOFDESC(mp)^.f_root;
vget(vp, LK_EXCLUSIVE or LK_RETRY);
vpp^:=vp;
Exit(0);
end;
function fdesc_statfs(mp:p_mount;sbp:p_statfs):Integer;
var
lim:Integer;
freefd:Integer;
begin
lim :=fd_table.fd_nfiles;
freefd:=fd_table.fd_freefd;
sbp^.f_flags :=0;
sbp^.f_bsize :=DEV_BSIZE;
sbp^.f_iosize:=DEV_BSIZE;
sbp^.f_blocks:=2; { 1K to keep df happy }
sbp^.f_bfree :=0;
sbp^.f_bavail:=0;
sbp^.f_files :=lim + 1; { Allow for '.' }
sbp^.f_ffree :=freefd;
Exit(0);
end;
end.