This commit is contained in:
Pavel 2023-05-19 16:01:11 +03:00
parent e34e71d189
commit 02b62690c1
7 changed files with 618 additions and 207 deletions

View File

@ -1059,7 +1059,7 @@ begin
Exit(error);
end;
function devfs_lookupx(ap:p_vop_lookup_args;dm_unlock:PInteger):Integer;
function devfs_lookupx(ap:p_vop_lookup_args;dm_unlock:PBoolean):Integer;
label
_or;
var
@ -1111,12 +1111,14 @@ begin
if ((flags and ISLASTCN)<>0) and (nameiop<>LOOKUP) then
Exit(EINVAL);
de:=devfs_parent_dirent(dd);
if (de=nil) then
Exit(ENOENT);
if (de=nil) then Exit(ENOENT);
dvplocked:=VOP_ISLOCKED(dvp);
VOP_UNLOCK(dvp, 0);
error:=devfs_allocv(de, dvp^.v_mount, cnp^.cn_lkflags and LK_TYPE_MASK, vpp);
dm_unlock^:=0;
dm_unlock^:=False;
vn_lock(dvp, dvplocked or LK_RETRY);
Exit(error);
end;
@ -1126,16 +1128,14 @@ begin
while (de=nil) do
begin { While(...) so we can use break }
if (nameiop=DELETE) then
Exit(ENOENT);
if (nameiop=DELETE) then Exit(ENOENT);
{
* OK, we didn't have an entry for the name we were asked for
* so we try to see if anybody can create it on demand.
}
pname:=devfs_fqpn(specname, dmp, dd, cnp);
if (pname=nil) then
break;
if (pname=nil) then break;
cdev:=nil;
DEVFS_DMP_HOLD(dmp);
@ -1150,24 +1150,28 @@ begin
else
if (devfs_populate_vp(dvp)<>0) then
begin
dm_unlock^:=0;
dm_unlock^:=false;
sx_xlock(@dmp^.dm_lock);
if (DEVFS_DMP_DROP(dmp)) then
begin
sx_xunlock(@dmp^.dm_lock);
devfs_unmount_final(dmp);
end else
sx_xunlock(@dmp^.dm_lock);
dev_rel(cdev);
Exit(ENOENT);
end;
if DEVFS_DMP_DROP(dmp) then
begin
dm_unlock^:=0;
dm_unlock^:=false;
sx_xunlock(@dmp^.dm_lock);
devfs_unmount_final(dmp);
if (cdev<>nil) then
dev_rel(cdev);
Exit(ENOENT);
end;
@ -1218,15 +1222,17 @@ begin
Exit(0);
end;
end;
error:=devfs_allocv(de, dvp^.v_mount, cnp^.cn_lkflags and LK_TYPE_MASK, vpp);
dm_unlock^:=0;
dm_unlock^:=false;
Exit(error);
end;
function devfs_lookup(ap:p_vop_lookup_args):Integer;
var
dmp:p_devfs_mount;
dm_unlock:Integer;
dm_unlock:Boolean;
begin
if (devfs_populate_vp(ap^.a_dvp)<>0) then
begin
@ -1234,10 +1240,11 @@ begin
end;
dmp:=VFSTODEVFS(ap^.a_dvp^.v_mount);
dm_unlock:=1;
dm_unlock:=True;
Result:=devfs_lookupx(ap, @dm_unlock);
if (dm_unlock=1) then
if (dm_unlock) then
begin
sx_xunlock(@dmp^.dm_lock);
end;
@ -1315,19 +1322,18 @@ begin
dev:=vp^.v_rdev;
fp:=ap^.a_fp;
if (vp^.v_type=VBLK) then
Exit(ENXIO);
if (dev=nil) then
Exit(ENXIO);
if (vp^.v_type=VBLK) then Exit(ENXIO);
if (dev=nil) then Exit(ENXIO);
{ Make this field valid before any I/O in d_open. }
if (dev^.si_iosize_max=0) then
begin
dev^.si_iosize_max:=DFLTPHYS;
end;
dsw:=dev_refthread(dev, @ref);
if (dsw=nil) then
Exit(ENXIO);
if (dsw=nil) then Exit(ENXIO);
if (fp=nil) and (dsw^.d_fdopen<>nil) then
begin
dev_relthread(dev, ref);
@ -1351,14 +1357,14 @@ begin
{ cleanup any cdevpriv upon error }
if (error<>0) then
devfs_clear_cdevpriv();
td^.td_fpop:=fpop;
vn_lock(vp, vlocked or LK_RETRY);
dev_relthread(dev, ref);
if (error<>0) then
begin
if (error=ERESTART) then
error:=EINTR;
if (error=ERESTART) then error:=EINTR;
Exit(error);
end;
@ -1366,7 +1372,10 @@ begin
Exit(error);
if (fp^.f_ops=@badfileops) then
begin
finit(fp, fp^.f_flag, DTYPE_VNODE, dev, @devfs_ops_f);
end;
mtxp:=mtx_pool_find(mtxpool_sleep, fp);
{

View File

@ -28,10 +28,13 @@ function md_mount(mp:p_ufs_mount):Integer;
function md_unmount(mp:p_ufs_mount):Integer;
function md_free_dirent(de:p_ufs_dirent):Integer;
function md_vmkdir(dmp:p_ufs_mount;name:PChar;namelen:Integer;dotdot:p_ufs_dirent;inode:DWORD):p_ufs_dirent;
function md_vmkdir(dmp:p_ufs_mount;name:PChar;namelen:Integer;dotdot:p_ufs_dirent):p_ufs_dirent;
function md_lookup(ap:p_vop_lookup_args):Integer;
function md_readdir(ap:p_vop_readdir_args):Integer;
function md_inactive(ap:p_vop_inactive_args):Integer;
function md_reclaim(ap:p_vop_reclaim_args):Integer;
function md_getattr(ap:p_vop_getattr_args):Integer;
const
md_vnodeops_host:vop_vector=(
@ -43,11 +46,11 @@ const
vop_create :nil;
vop_whiteout :nil;
vop_mknod :nil;
vop_open :nil;
vop_close :nil;
vop_open :nil; //TODO
vop_close :nil; //TODO
vop_access :nil; //parent
vop_accessx :nil;
vop_getattr :@ufs_getattr;
vop_getattr :@md_getattr;
vop_setattr :@ufs_setattr;
vop_markatime :nil;
vop_read :nil; //parent
@ -56,17 +59,17 @@ const
vop_poll :nil;
vop_kqfilter :nil;
vop_revoke :nil;
vop_fsync :nil;
vop_remove :@ufs_remove;
vop_link :nil;
vop_rename :nil;
vop_mkdir :@ufs_mkdir;
vop_rmdir :@ufs_rmdir;
vop_symlink :@ufs_symlink;
vop_fsync :nil; //TODO
vop_remove :nil; //TODO
vop_link :nil; //TODO
vop_rename :nil; //TODO
vop_mkdir :nil; //TODO
vop_rmdir :nil; //TODO
vop_symlink :nil; //TODO
vop_readdir :@md_readdir;
vop_readlink :@ufs_readlink;
vop_inactive :nil;
vop_reclaim :@ufs_reclaim;
vop_inactive :@md_inactive;
vop_reclaim :@md_reclaim;
vop_lock1 :nil;
vop_unlock :nil;
vop_bmap :nil;
@ -123,17 +126,22 @@ begin
Result:=mp^.mnt_data;
end;
procedure INIT_OBJ(var OBJ:TOBJ_ATTR;fd:THandle;FileName:PWideChar);
function INIT_UNICODE(FileName:PWideChar):UNICODE_STRING;
begin
Result.Length :=strlen(FileName)*SizeOf(WideChar);
Result.MaximumLength:=Result.Length+1;
Result.Buffer :=FileName;
end;
procedure INIT_OBJ(var OBJ:TOBJ_ATTR;fd:THandle;attr:ULONG;FileName:PWideChar);
begin
OBJ.OATTR.Length:=SizeOf(OBJECT_ATTRIBUTES);
OBJ.OATTR.RootDirectory:=fd;
OBJ.OATTR.ObjectName :=@OBJ.UPATH;
OBJ.OATTR.Attributes :=OBJ_CASE_INSENSITIVE;
OBJ.OATTR.Attributes :=attr;
OBJ.UPATH.Length :=strlen(FileName)*SizeOf(WideChar);
OBJ.UPATH.MaximumLength:=OBJ.UPATH.Length+1;
OBJ.UPATH.Buffer :=FileName;
OBJ.UPATH:=INIT_UNICODE(FileName);
end;
function ntf2px(n:Integer):Integer; inline;
@ -189,6 +197,11 @@ begin
end;
end;
function get_inode(i:LARGE_INTEGER):Integer; inline;
begin
Result:=(i.LowPart+i.HighPart); //simple hash
end;
function md_mount(mp:p_ufs_mount):Integer;
var
w:WideString;
@ -201,7 +214,7 @@ begin
w:='\??\'+w;
OBJ:=Default(TOBJ_ATTR);
INIT_OBJ(OBJ,0,PWideChar(w));
INIT_OBJ(OBJ,0,OBJ_CASE_INSENSITIVE,PWideChar(w));
BLK:=Default(IO_STATUS_BLOCK);
R:=NtOpenFile(@F,
@ -220,31 +233,112 @@ end;
function md_unmount(mp:p_ufs_mount):Integer;
begin
NtClose(THandle(mp^.ufs_md_fp));
if (mp^.ufs_md_fp<>nil) then
begin
NtClose(THandle(mp^.ufs_md_fp));
end;
Result:=0;
end;
function md_free_dirent(de:p_ufs_dirent):Integer;
begin
NtClose(THandle(de^.ufs_md_fp));
if (de^.ufs_md_fp<>nil) then
begin
NtClose(THandle(de^.ufs_md_fp));
end;
Result:=0;
end;
function md_update_dirent(de:p_ufs_dirent):Integer;
function md_open_dirent(de:p_ufs_dirent):Integer;
var
u:RawByteString;
w:WideString;
OBJ:TOBJ_ATTR;
BLK:IO_STATUS_BLOCK;
F:Thandle;
R:DWORD;
begin
SetString(u,@de^.ufs_dirent^.d_name,de^.ufs_dirent^.d_namlen);
w:=UTF8Decode(u);
OBJ:=Default(TOBJ_ATTR);
INIT_OBJ(OBJ,THandle(de^.ufs_dir^.ufs_md_fp),0,PWideChar(w));
BLK:=Default(IO_STATUS_BLOCK);
R:=NtOpenFile(@F,
SYNCHRONIZE or FILE_LIST_DIRECTORY or FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES,
@OBJ,
@BLK,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
FILE_OPEN_FOR_BACKUP_INTENT or FILE_SYNCHRONOUS_IO_NONALERT or FILE_DIRECTORY_FILE
);
Result:=ntf2px(R);
if (Result<>0) then Exit;
de^.ufs_md_fp:=Pointer(F);
end;
function md_open_dirent_file(de:p_ufs_dirent;fdr:PHandle):Integer;
var
u:RawByteString;
w:WideString;
OBJ:TOBJ_ATTR;
BLK:IO_STATUS_BLOCK;
F:Thandle;
R:DWORD;
begin
SetString(u,@de^.ufs_dirent^.d_name,de^.ufs_dirent^.d_namlen);
w:=UTF8Decode(u);
OBJ:=Default(TOBJ_ATTR);
INIT_OBJ(OBJ,THandle(de^.ufs_dir^.ufs_md_fp),0,PWideChar(w));
BLK:=Default(IO_STATUS_BLOCK);
R:=NtOpenFile(@F,
SYNCHRONIZE or FILE_READ_DATA or FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES,
@OBJ,
@BLK,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
FILE_OPEN_FOR_BACKUP_INTENT or FILE_SYNCHRONOUS_IO_NONALERT
);
Result:=ntf2px(R);
if (Result<>0) then Exit;
fdr^:=F;
end;
function md_update_dirent(de:p_ufs_dirent):Integer;
label
_exit;
var
FP,RL:THandle;
FBI:FILE_BASIC_INFORMATION;
//FSI:FILE_STANDARD_INFORMATION;
FSI:FILE_STANDARD_INFORMATION;
FII:FILE_INTERNAL_INFORMATION;
BLK:IO_STATUS_BLOCK;
R:DWORD;
begin
//ufs_inode (4) = FileInternalInformation (8) ??? hash it?
if (de=nil) then Exit(0);
if (de^.ufs_md_fp=nil) then
begin
Result:=md_open_dirent_file(de,@FP);
if (Result<>0) then Exit;
RL:=FP;
end else
begin
FP:=THandle(de^.ufs_md_fp);
RL:=0;
end;
FBI:=Default(FILE_BASIC_INFORMATION);
//FSI:=Default(FILE_STANDARD_INFORMATION);
BLK:=Default(IO_STATUS_BLOCK);
R:=NtQueryInformationFile(
THandle(de^.ufs_md_fp),
FP,
@BLK,
@FBI,
SizeOf(FBI),
@ -252,18 +346,20 @@ begin
);
Result:=ntf2px(R);
if (Result<>0) then Exit;
if (Result<>0) then goto _exit;
de^.ufs_atime:=get_unix_file_time(FBI.LastAccessTime);
de^.ufs_mtime:=get_unix_file_time(FBI.LastWriteTime);
de^.ufs_ctime:=get_unix_file_time(FBI.ChangeTime);
de^.ufs_btime:=get_unix_file_time(FBI.CreationTime);
{
////
FSI:=Default(FILE_STANDARD_INFORMATION);
BLK:=Default(IO_STATUS_BLOCK);
R:=NtQueryInformationFile(
THandle(de^.ufs_md_fp),
FP,
@BLK,
@FSI,
SizeOf(FSI),
@ -271,10 +367,42 @@ begin
);
Result:=ntf2px(R);
if (Result<>0) then Exit;
if (Result<>0) then goto _exit;
de^.ufs_links:=FSI.NumberOfLinks;
}
if (de^.ufs_dirent^.d_type<>DT_DIR) then
begin
de^.ufs_links:=FSI.NumberOfLinks;
de^.ufs_size :=Int64(FSI.EndOfFile);
de^.ufs_bytes:=Int64(FSI.AllocationSize);
end;
////
if (de^.ufs_inode=0) then
begin
FII:=Default(FILE_INTERNAL_INFORMATION);
BLK:=Default(IO_STATUS_BLOCK);
R:=NtQueryInformationFile(
FP,
@BLK,
@FII,
SizeOf(FII),
FileInternalInformation
);
Result:=ntf2px(R);
if (Result<>0) then goto _exit;
de^.ufs_inode:=get_inode(FII.IndexNumber);
de^.ufs_dirent^.d_fileno:=de^.ufs_inode;
end;
_exit:
if (RL<>0) then
begin
NtClose(RL);
end;
end;
function md_newdirent(name:PChar;namelen:Integer):p_ufs_dirent;
@ -297,10 +425,13 @@ begin
de^.ufs_links :=1;
de^.ufs_ref :=1;
sx_init(@de^.ufs_md_lock, 'md_lock');
TAILQ_INIT(@de^.ufs_dlist);
Exit(de);
end;
function md_vmkdir(dmp:p_ufs_mount;name:PChar;namelen:Integer;dotdot:p_ufs_dirent;inode:DWORD):p_ufs_dirent;
function md_vmkdir(dmp:p_ufs_mount;name:PChar;namelen:Integer;dotdot:p_ufs_dirent):p_ufs_dirent;
var
nd:p_ufs_dirent;
error:Integer;
@ -308,37 +439,261 @@ begin
{ Create the new directory }
nd:=md_newdirent(name, namelen);
TAILQ_INIT(@nd^.ufs_dlist);
nd^.ufs_dirent^.d_type:=DT_DIR;
nd^.ufs_mode :=&0555;
nd^.ufs_mode :=&0777;
nd^.ufs_links:=2;
nd^.ufs_dir :=nd;
if (inode<>0) then
nd^.ufs_inode:=inode
else
nd^.ufs_inode:=ufs_alloc_cdp_inode;
nd^.ufs_dir :=dotdot;
if (dotdot=nil) then
begin
//move root handle
nd^.ufs_md_fp:=dmp^.ufs_md_fp;
end else
begin
//nd^.ufs_md_fp:=???
sx_assert(@dmp^.ufs_lock);
error:=md_open_dirent(nd);
if (error<>0) then
begin
ufs_de_drop(nd);
Exit(nil);
end;
sx_assert(@dotdot^.ufs_md_lock);
TAILQ_INSERT_TAIL(@dotdot^.ufs_dlist,nd,@nd^.ufs_list);
Inc(dotdot^.ufs_links);
ufs_de_hold(dotdot);
end;
error:=md_update_dirent(nd);
Assert(error=0);
if (error<>0) then
begin
ufs_de_drop(nd);
Exit(nil);
end;
Exit(nd);
end;
function md_find_cache(dd:p_ufs_dirent;name:PChar;namelen:Integer;_type:Integer):p_ufs_dirent;
var
de:p_ufs_dirent;
begin
sx_assert(@dd^.ufs_md_lock);
function md_lookupx(dmp:p_ufs_mount;ap:p_vop_lookup_args):Integer;
de:=TAILQ_FIRST(@dd^.ufs_dlist);
while (de<>nil) do
begin
if (namelen<>de^.ufs_dirent^.d_namlen) then
begin
de:=TAILQ_NEXT(de,@de^.ufs_list);
continue;
end;
if (_type<>0) and (_type<>de^.ufs_dirent^.d_type) then
begin
de:=TAILQ_NEXT(de,@de^.ufs_list);
continue;
end;
if (CompareByte(name^, de^.ufs_dirent^.d_name, namelen)<>0) then
begin
de:=TAILQ_NEXT(de,@de^.ufs_list);
continue;
end;
break;
end;
Exit(de);
end;
function md_lookup_dirent(dd:p_ufs_dirent;name:PChar;namelen:Integer):p_ufs_dirent;
var
u:RawByteString;
w:WideString;
nd:p_ufs_dirent;
de:p_dirent;
UNAME:UNICODE_STRING;
NT_DIRENT:TNT_DIRENT;
BLK:IO_STATUS_BLOCK;
R:DWORD;
begin
sx_assert(@dd^.ufs_md_lock);
Result:=nil;
SetString(u,name,namelen);
w:=UTF8Decode(u);
UNAME:=INIT_UNICODE(PWideChar(w));
NT_DIRENT:=Default(TNT_DIRENT);
BLK:=Default(IO_STATUS_BLOCK);
R:=NtQueryDirectoryFile(
THandle(dd^.ufs_md_fp),
0,
nil,
nil,
@BLK,
@NT_DIRENT,
SizeOf(NT_DIRENT),
FileIdFullDirectoryInformation,
True,
@UNAME,
True
);
if (R<>0) then Exit;
{ Create the new directory }
nd:=md_newdirent(name, namelen);
nd^.ufs_mode :=&0777;
nd^.ufs_links:=1; //read link???
nd^.ufs_dir :=dd;
if ((NT_DIRENT.Info.FileAttributes and FILE_ATTRIBUTE_DIRECTORY)=0) then
begin
nd^.ufs_size :=Int64(NT_DIRENT.Info.EndOfFile);
nd^.ufs_bytes:=Int64(NT_DIRENT.Info.AllocationSize);
end;
nd^.ufs_inode:=get_inode(NT_DIRENT.Info.FileId);
nd^.ufs_atime:=get_unix_file_time(NT_DIRENT.Info.LastAccessTime);
nd^.ufs_mtime:=get_unix_file_time(NT_DIRENT.Info.LastWriteTime);
nd^.ufs_ctime:=get_unix_file_time(NT_DIRENT.Info.ChangeTime);
nd^.ufs_btime:=get_unix_file_time(NT_DIRENT.Info.CreationTime);
de:=nd^.ufs_dirent;
de^.d_fileno:=nd^.ufs_inode;
de^.d_type :=NT_FA_TO_DT(NT_DIRENT.Info.FileAttributes,NT_DIRENT.Info.EaSize);
if (de^.d_type=DT_DIR) then
begin
R:=md_open_dirent(nd);
if (R<>0) then
begin
ufs_de_drop(nd);
Exit(nil);
end;
end;
TAILQ_INSERT_TAIL(@dd^.ufs_dlist,nd,@nd^.ufs_list);
Inc(dd^.ufs_links);
ufs_de_hold(dd);
Exit(nd);
end;
procedure md_delete_cache(de:p_ufs_dirent);
var
dd:p_ufs_dirent;
vp:p_vnode;
begin
if (de=nil) then Exit;
Assert((de^.ufs_flags and UFS_DOOMED)=0,'ufs_delete doomed dirent');
de^.ufs_flags:=de^.ufs_flags or UFS_DOOMED;
dd:=de^.ufs_dir; //parent
if (dd<>nil) then
begin
ufs_de_hold(dd);
sx_xlock(@dd^.ufs_md_lock);
end;
mtx_lock(ufs_interlock);
vp:=de^.ufs_vnode;
if (vp<>nil) then
begin
VI_LOCK(vp);
mtx_unlock(ufs_interlock);
vholdl(vp);
if (dd<>nil) then
begin
sx_unlock(@dd^.ufs_md_lock);
end;
vn_lock(vp, LK_EXCLUSIVE or LK_INTERLOCK or LK_RETRY);
vgone(vp);
VOP_UNLOCK(vp, 0);
vdrop(vp);
if (dd<>nil) then
begin
sx_xlock(@dd^.ufs_md_lock);
end;
end else
mtx_unlock(ufs_interlock);
if (de^.ufs_symlink<>nil) then
begin
FreeMem(de^.ufs_symlink);
de^.ufs_symlink:=nil;
end;
if (dd<>nil) then
begin
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
sx_unlock(@dd^.ufs_md_lock);
ufs_de_drop(dd);
ufs_de_drop(dd);
end;
ufs_de_drop(de);
end;
function md_inactive(ap:p_vop_inactive_args):Integer;
var
vp:p_vnode;
de:p_ufs_dirent;
begin
vp:=ap^.a_vp;
mtx_lock(ufs_interlock);
de:=vp^.v_data;
if (de<>nil) then
begin
de^.ufs_vnode:=nil;
vp^.v_data:=nil;
end;
mtx_unlock(ufs_interlock);
md_delete_cache(de);
Exit(0);
end;
function md_reclaim(ap:p_vop_reclaim_args):Integer;
var
vp:p_vnode;
de:p_ufs_dirent;
begin
vp:=ap^.a_vp;
mtx_lock(ufs_interlock);
de:=vp^.v_data;
if (de<>nil) then
begin
de^.ufs_vnode:=nil;
vp^.v_data:=nil;
end;
mtx_unlock(ufs_interlock);
md_delete_cache(de);
//vnode_destroy_vobject(vp);
Exit(0);
end;
function md_lookupx(ap:p_vop_lookup_args):Integer;
label
_error;
var
cnp:p_componentname;
dvp:p_vnode;
@ -347,6 +702,7 @@ var
dde:p_ufs_dirent;
error,flags,nameiop,dvplocked:Integer;
pname:PChar;
dmp:p_ufs_mount;
begin
cnp:=ap^.a_cnp;
vpp:=ap^.a_vpp;
@ -357,32 +713,102 @@ begin
dd:=dvp^.v_data;
vpp^:=nil;
////////
if (dvp^.v_type<>VDIR) then
Exit(ENOTDIR);
Exit(ENOENT);
if (((flags and ISDOTDOT)<>0) and ((dvp^.v_vflag and VV_ROOT)<>0)) then
Exit(EIO);
error:=VOP_ACCESS(dvp, VEXEC);
if (error<>0) then
Exit(error);
if (cnp^.cn_namelen=1) and (pname^='.') then
begin
if ((flags and ISLASTCN) and nameiop<>LOOKUP) then
Exit(EINVAL);
vpp^:=dvp;
VREF(dvp);
Exit(0);
end;
de:=md_find_cache(dd, cnp^.cn_nameptr, cnp^.cn_namelen, 0);
if (de=nil) then
begin
de:=md_lookup_dirent(dd, cnp^.cn_nameptr, cnp^.cn_namelen);
end;
if (de=nil) then
begin
Case nameiop of
CREATE:
begin
//if not last
if ((flags and ISLASTCN)=0) then Exit(ENOENT);
end;
LOOKUP,
DELETE,
RENAME:Exit(ENOENT);
else;
end;
goto _error;
end;
if ((de^.ufs_flags and UFS_WHITEOUT)<>0) then
begin
_error:
if ((nameiop=CREATE) or (nameiop=RENAME)) and
((flags and (LOCKPARENT or WANTPARENT))<>0) and
((flags and ISLASTCN)<>0) then
begin
cnp^.cn_flags:=cnp^.cn_flags or SAVENAME;
Exit(EJUSTRETURN);
end;
Exit(ENOENT);
end;
if (cnp^.cn_nameiop=DELETE) and ((flags and ISLASTCN)<>0) then
begin
error:=VOP_ACCESS(dvp, VWRITE);
if (error<>0) then
Exit(error);
if (vpp^=dvp) then
begin
VREF(dvp);
vpp^:=dvp;
Exit(0);
end;
end;
dmp:=VFSTOUFS(ap^.a_dvp^.v_mount);
sx_xlock(@dmp^.ufs_lock);
error:=ufs_allocv(de, dvp^.v_mount, cnp^.cn_lkflags and LK_TYPE_MASK, vpp);
Exit(error);
end;
function md_lookup(ap:p_vop_lookup_args):Integer;
var
dmp:p_ufs_mount;
dd:p_ufs_dirent;
begin
dmp:=VFSTOUFS(ap^.a_dvp^.v_mount);
sx_xlock(@dmp^.ufs_lock);
Result:=md_lookupx(dmp,ap);
sx_xunlock(@dmp^.ufs_lock);
dd:=ap^.a_dvp^.v_data;
sx_xlock(@dd^.ufs_md_lock);
Result:=md_lookupx(ap);
sx_xunlock(@dd^.ufs_md_lock);
end;
function md_readdir(ap:p_vop_readdir_args):Integer;
var
uio:p_uio;
//mp:p_mount;
//dmp:p_ufs_mount;
dd:p_ufs_dirent;
dt:t_dirent;
off:Int64;
NT_DIRENT:TNT_DIRENT;
@ -397,14 +823,12 @@ begin
if (uio^.uio_offset < 0) then
Exit(EINVAL);
//mp:=ap^.a_vp^.v_mount;
//dmp:=VFSTOUFS(mp);
dd:=ap^.a_vp^.v_data;
off:=0;
restart:=True;
sx_xlock(@dd^.ufs_md_lock);
repeat
NT_DIRENT:=Default(TNT_DIRENT);
BLK:=Default(IO_STATUS_BLOCK);
@ -427,7 +851,7 @@ begin
if (R=STATUS_NO_MORE_FILES) then Break;
Result:=ntf2px(R);
if (Result<>0) then Exit;
if (Result<>0) then Break;
dt:=Default(t_dirent);
dt.d_reclen:=SizeOf(t_dirent)-(t_dirent.MAXNAMLEN+1)+NT_DIRENT.Info.FileNameLength;
@ -436,7 +860,7 @@ begin
if (off >= uio^.uio_offset) then
begin
dt.d_fileno:=NT_DIRENT.Info.FileIndex; // FileId ????
dt.d_fileno:=get_inode(NT_DIRENT.Info.FileId);
//dt.d_reclen
dt.d_type :=NT_FA_TO_DT(NT_DIRENT.Info.FileAttributes,NT_DIRENT.Info.EaSize);
dt.d_namlen:=NT_DIRENT.Info.FileNameLength-1;
@ -449,10 +873,26 @@ begin
Inc(off,dt.d_reclen);
until false;
sx_xunlock(@dd^.ufs_md_lock);
uio^.uio_offset:=off;
Exit(0);
end;
function md_getattr(ap:p_vop_getattr_args):Integer;
var
vp:p_vnode;
de:p_ufs_dirent;
begin
vp:=ap^.a_vp;
de:=vp^.v_data;
Result:=md_update_dirent(de);
if (Result<>0) then Exit;
Result:=ufs_getattr(ap);
end;
end.

View File

@ -31,12 +31,15 @@ type
ufs_mode :mode_t; //S_IFMT
ufs_uid :uid_t;
ufs_gid :gid_t;
ufs_size :Int64; // file size in bytes
ufs_bytes :Int64; // bytes of disk space held by file
ufs_atime :timespec; // time of last access
ufs_mtime :timespec; // time of last data modification
ufs_ctime :timespec; // time of last file status change
ufs_btime :timespec; // time of file creation
ufs_vnode :p_vnode;
ufs_symlink:PChar;
ufs_md_lock:t_sx;
ufs_md_fp :Pointer; //host data
end;
@ -181,6 +184,7 @@ begin
if (System.InterlockedDecrement(p^.ufs_ref)=0) then
begin
md_free_dirent(p);
sx_destroy(@p^.ufs_md_lock);
FreeMem(p);
Result:=True;
end;
@ -348,6 +352,9 @@ begin
end;
function ufs_mount(mp:p_mount):Integer;
label
_err,
_mount_err;
var
error:Integer;
fmp:p_ufs_mount;
@ -425,25 +432,26 @@ begin
fmp^.ufs_vnops:=@md_vnodeops_host;
error:=md_mount(fmp);
if (error<>0) then
begin
sx_xlock(@fmp^.ufs_lock);
ufs_purge(fmp,fmp^.ufs_rootdir);
sx_xunlock(@fmp^.ufs_lock);
sx_destroy(@fmp^.ufs_lock);
//free_unr(ufs_unr, fmp^.ufs_idx);
FreeMem(fmp);
Exit(error);
end;
if (error<>0) then goto _mount_err;
fmp^.ufs_rootdir:=md_vmkdir(fmp, nil, 0, nil, UFS_ROOTINO);
fmp^.ufs_rootdir:=md_vmkdir(fmp, nil, 0, nil);
end;
if (fmp^.ufs_rootdir=nil) then
begin
error:=EINVAL; //??
goto _err;
end;
error:=ufs_root(mp, LK_EXCLUSIVE, @rvp);
if (error<>0) then
begin
_err:
md_unmount(fmp);
_mount_err:
sx_xlock(@fmp^.ufs_lock);
ufs_purge(fmp,fmp^.ufs_rootdir);
sx_xunlock(@fmp^.ufs_lock);
sx_destroy(@fmp^.ufs_lock);
//free_unr(ufs_unr, fmp^.ufs_idx);
FreeMem(fmp);

View File

@ -128,10 +128,10 @@ begin
Exit(nil);
de:=TAILQ_FIRST(@de^.ufs_dlist); { '.' }
if (de=nil) then Exit(nil);
if (de=nil) then Exit(de^.ufs_dir);
de:=TAILQ_NEXT(de,@de^.ufs_list); { '..' }
if (de=nil) then Exit(nil);
if (de=nil) then Exit(de^.ufs_dir);
Exit(de^.ufs_dir);
end;
@ -161,6 +161,8 @@ begin
de^.ufs_links :=1;
de^.ufs_ref :=1;
TAILQ_INIT(@de^.ufs_dlist);
Exit(de);
end;
@ -200,6 +202,7 @@ begin
VI_LOCK(vp);
mtx_unlock(ufs_interlock);
vholdl(vp);
sx_unlock(@dm^.ufs_lock);
if ((flags and UFS_DEL_VNLOCKED)=0) then
@ -229,10 +232,9 @@ begin
de^.ufs_inode:=0;
end;
ufs_de_drop(de);
if (dd<>nil) then
begin
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
if ufs_de_drop(dd) then
begin
//
@ -243,6 +245,7 @@ begin
end;
end;
ufs_de_drop(de);
end;
function _ufs_dir_status(dm:p_ufs_mount;de:p_ufs_dirent):Integer;
@ -293,13 +296,13 @@ begin
de_dot:=TAILQ_FIRST(@de^.ufs_dlist);
if (de_dot=nil) then
begin
//goto
goto next;
end;
de_dotdot:=TAILQ_NEXT(de_dot,@de_dot^.ufs_list);
if (de_dotdot=nil) then
begin
//goto
goto next;
end;
{ Exit if the directory is not empty. }
@ -310,19 +313,6 @@ begin
next:
if (de_dot<>nil) then
begin
TAILQ_REMOVE(@de^.ufs_dlist,de_dot,@de_dot^.ufs_list);
end;
if (de_dotdot<>nil) then
begin
TAILQ_REMOVE(@de^.ufs_dlist,de_dotdot,@de_dotdot^.ufs_list);
end;
if (dd<>nil) then
begin
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
end;
ufs_de_hold(dd);
ufs_delete(dm, de ,UFS_DEL_NORECURSE);
ufs_delete(dm, de_dot ,UFS_DEL_NORECURSE);
@ -337,12 +327,11 @@ begin
sx_assert(@dm^.ufs_lock);
ufs_de_hold(dd);
repeat
de:=TAILQ_LAST(@dd^.ufs_dlist);
if (de=nil) then break;
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
if ((de^.ufs_flags and (UFS_DOT or UFS_DOTDOT))<>0) then
ufs_delete(dm, de, UFS_DEL_NORECURSE)
else
@ -353,10 +342,10 @@ begin
until false;
ufs_de_drop(dd);
if ((dd^.ufs_flags and UFS_DOOMED)=0) then
ufs_delete(dm, dd, UFS_DEL_NORECURSE);
ufs_de_drop(dd);
end;
function ufs_vmkdir(dmp:p_ufs_mount;name:PChar;namelen:Integer;dotdot:p_ufs_dirent;inode:DWORD):p_ufs_dirent;
@ -367,10 +356,8 @@ begin
{ Create the new directory }
nd:=ufs_newdirent(name, namelen);
TAILQ_INIT(@nd^.ufs_dlist);
nd^.ufs_dirent^.d_type:=DT_DIR;
nd^.ufs_mode :=&0555;
nd^.ufs_mode :=&0777;
nd^.ufs_links:=2;
nd^.ufs_dir :=nd;
@ -448,16 +435,14 @@ begin
Exit(de);
end;
function ufs_lookupx(ap:p_vop_lookup_args;dm_unlock:PInteger):Integer;
function ufs_lookupx(ap:p_vop_lookup_args;dm_unlock:PBoolean):Integer;
label
_or;
_error;
var
cnp:p_componentname;
dvp:p_vnode;
vpp:pp_vnode;
de,dd:p_ufs_dirent;
dde:p_ufs_dirent;
dmp:p_ufs_mount;
error,flags,nameiop,dvplocked:Integer;
pname:PChar;
begin
@ -467,14 +452,11 @@ begin
pname:=cnp^.cn_nameptr;
flags:=cnp^.cn_flags;
nameiop:=cnp^.cn_nameiop;
dmp:=VFSTOUFS(dvp^.v_mount);
dd:=dvp^.v_data;
vpp^:=nil;
dm_unlock^:=0;
//if ((flags and ISLASTCN)<>0) and (nameiop=RENAME) then
// Exit(EOPNOTSUPP);
if ((flags and ISLASTCN)<>0) and (nameiop=RENAME) then
Exit(EOPNOTSUPP);
if (dvp^.v_type<>VDIR) then
Exit(ENOTDIR);
@ -497,9 +479,6 @@ begin
Exit(0);
end;
dm_unlock^:=1;
sx_xlock(@dmp^.ufs_lock);
if ((flags and ISDOTDOT)<>0) then
begin
if ((flags and ISLASTCN)<>0) and (nameiop<>LOOKUP) then
@ -512,19 +491,19 @@ begin
dvplocked:=VOP_ISLOCKED(dvp);
VOP_UNLOCK(dvp, 0);
error:=ufs_allocv(de, dvp^.v_mount, cnp^.cn_lkflags and LK_TYPE_MASK, vpp);
dm_unlock^:=false;
vn_lock(dvp, dvplocked or LK_RETRY);
dm_unlock^:=0;
Exit(error);
end;
dd:=dvp^.v_data;
de:=ufs_find(dd, cnp^.cn_nameptr, cnp^.cn_namelen, 0);
while (de=nil) do
begin { While(...) so we can use break }
if (de=nil) then
begin
Case nameiop of
CREATE:
begin
@ -537,23 +516,12 @@ begin
RENAME:Exit(ENOENT);
else;
end;
{
* OK, we didn't have an entry for the name we were asked for
* so we try to see if anybody can create it on demand.
}
pname:=cnp^.cn_nameptr;
if (pname=nil) then
break;
break;
goto _error;
end;
if (de=nil) then goto _or;
if ((de^.ufs_flags and UFS_WHITEOUT)<>0) then
begin
_or:
_error:
if ((nameiop=CREATE) or (nameiop=RENAME)) and
((flags and (LOCKPARENT or WANTPARENT))<>0) and
((flags and ISLASTCN)<>0) then
@ -579,22 +547,24 @@ begin
end;
error:=ufs_allocv(de, dvp^.v_mount, cnp^.cn_lkflags and LK_TYPE_MASK, vpp);
dm_unlock^:=false;
dm_unlock^:=0;
Exit(error);
end;
function ufs_lookup(ap:p_vop_lookup_args):Integer;
var
dmp:p_ufs_mount;
dm_unlock:Integer;
dm_unlock:Boolean;
begin
dmp:=VFSTOUFS(ap^.a_dvp^.v_mount);
dm_unlock:=1;
dm_unlock:=True;
sx_xlock(@dmp^.ufs_lock);
Result:=ufs_lookupx(ap, @dm_unlock);
if (dm_unlock=1) then
if (dm_unlock) then
begin
sx_xunlock(@dmp^.ufs_lock);
end;
@ -629,16 +599,9 @@ var
vap:p_vattr;
de:p_ufs_dirent;
procedure fix(var src,dst:timespec); inline;
begin
dst:=src;
end;
begin
vp:=ap^.a_vp;
vap:=ap^.a_vap;
de:=vp^.v_data;
vap^.va_uid :=de^.ufs_uid;
@ -658,8 +621,8 @@ begin
end;
else
begin
vap^.va_size :=0;
vap^.va_bytes:=0;
vap^.va_size :=de^.ufs_size;
vap^.va_bytes:=de^.ufs_bytes;
end;
end;
@ -805,12 +768,12 @@ begin
mp:=ap^.a_vp^.v_mount;
dmp:=VFSTOUFS(mp);
sx_xlock(@dmp^.ufs_lock);
error:=0;
de:=ap^.a_vp^.v_data;
off:=0;
sx_xlock(@dmp^.ufs_lock);
dd:=TAILQ_FIRST(@de^.ufs_dlist);
while (dd<>nil) do
begin
@ -895,7 +858,7 @@ begin
de^.ufs_flags:=UFS_USER;
de^.ufs_uid :=0;
de^.ufs_gid :=0;
de^.ufs_mode :=&0755;
de^.ufs_mode :=&0777;
de^.ufs_inode:=ufs_alloc_cdp_inode;
de^.ufs_dir :=dd;
de^.ufs_dirent^.d_type:=DT_LNK;
@ -906,7 +869,7 @@ begin
TAILQ_INSERT_TAIL(@dd^.ufs_dlist,de,@de^.ufs_list);
Exit(ufs_allocv(de, ap^.a_dvp^.v_mount, LK_EXCLUSIVE, ap^.a_vpp));
Exit(ufs_allocv(de, ap^.a_dvp^.v_mount, LK_EXCLUSIVE, ap^.a_vpp)); //sx_xunlock
end;
function ufs_remove(ap:p_vop_remove_args):Integer;
@ -937,8 +900,6 @@ begin
end;
end;
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
if (de^.ufs_dirent^.d_type=DT_LNK) then
begin
de_cov:=ufs_find(dd, de^.ufs_dirent^.d_name, de^.ufs_dirent^.d_namlen, 0);
@ -994,8 +955,6 @@ begin
Exit;
end;
TAILQ_REMOVE(@dd^.ufs_dlist,de,@de^.ufs_list);
VOP_UNLOCK(vp, 0);
if (dvp<>vp) then
@ -1046,7 +1005,7 @@ begin
de^.ufs_mode :=vap^.va_mode;
Exit(ufs_allocv(de, ap^.a_dvp^.v_mount, LK_EXCLUSIVE, ap^.a_vpp));
Exit(ufs_allocv(de, ap^.a_dvp^.v_mount, LK_EXCLUSIVE, ap^.a_vpp)); //sx_xunlock
end;
function ufs_reclaim(ap:p_vop_reclaim_args):Integer;

View File

@ -281,7 +281,7 @@ begin
'.',
'..':
begin
Writeln(Space(s),namep,' |');
Writeln(Space(s),namep:20,' |');
Exit;
end;
else;
@ -289,19 +289,12 @@ begin
err:=sys_lstat(PChar(dirp+namep),@sb);
//if (err=45) then
//begin
// sb.st_size:=512;
// sb.st_mode:=S_IFMT;
// goto _next;
//end;
if (err<>0) then
begin
Writeln(Space(s),namep,' | (',err,')');
Writeln(Space(s),namep:20,' | (',err,')');
end else
begin
Write(Space(s),namep,' | ',ts_to_str(sb.st_birthtim {st_mtim}),' |');
Write(Space(s),namep:20,' | ',ts_to_str(sb.st_birthtim {st_mtim}):19,' |');
_next:
if ((sb.st_mode and S_IFDIR)<>0) then

View File

@ -2413,11 +2413,13 @@ begin
error:=getvnode(fd, CAP_FSYNC, @fp);
if (error<>0) then
Exit(error);
vp:=fp^.f_vnode;
vfslocked:=VFS_LOCK_GIANT(vp^.v_mount);
error:=vn_start_write(vp, @mp, V_WAIT or PCATCH);
if (error<>0) then
goto drop;
if MNT_SHARED_WRITES(mp) or
((mp=nil) and MNT_SHARED_WRITES(vp^.v_mount)) then
begin

View File

@ -277,26 +277,26 @@ type
p_vattr=^t_vattr;
t_vattr=record
va_type :vtype;
va_mode :SmallInt;
va_nlink :SmallInt;
va_uid :Integer;
va_gid :Integer;
va_fsid :Int64;
va_fileid :Integer;
va_size :Int64;
va_blocksize:Integer;
va_atime :timespec;
va_mtime :timespec;
va_ctime :timespec;
va_birthtime:timespec;
va_gen :Integer;
va_flags :Integer;
va_rdev :Integer;
va_bytes :Int64;
va_filerev :Int64;
va_vaflags :Integer;
va_spare :Integer;
va_type :vtype; // vnode type (for create)
va_mode :SmallInt; // files access mode and type
va_nlink :SmallInt; // number of references to file
va_uid :Integer; // owner user id
va_gid :Integer; // owner group id
va_fsid :Int64; // filesystem id
va_fileid :Integer; // file id
va_size :Int64; // file size in bytes
va_blocksize:Integer; // blocksize preferred for i/o
va_atime :timespec; // time of last access
va_mtime :timespec; // time of last modification
va_ctime :timespec; // time file changed
va_birthtime:timespec; // time file created
va_gen :Integer; // generation number of file
va_flags :Integer; // flags defined for file
va_rdev :Integer; // device the special file represents
va_bytes :Int64; // bytes of disk space held by file
va_filerev :Int64; // file modification number
va_vaflags :Integer; // operations flags, see below
va_spare :Integer; // remain quad aligned
end;
const