diff --git a/sys/fs/devfs/devfs_vnops.pas b/sys/fs/devfs/devfs_vnops.pas index 8ef2020d..ef10e806 100644 --- a/sys/fs/devfs/devfs_vnops.pas +++ b/sys/fs/devfs/devfs_vnops.pas @@ -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); { diff --git a/sys/fs/ufs/md_vnops.pas b/sys/fs/ufs/md_vnops.pas index e4993e1c..1cc1e9ef 100644 --- a/sys/fs/ufs/md_vnops.pas +++ b/sys/fs/ufs/md_vnops.pas @@ -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. diff --git a/sys/fs/ufs/ufs.pas b/sys/fs/ufs/ufs.pas index 716d2f16..a0b19409 100644 --- a/sys/fs/ufs/ufs.pas +++ b/sys/fs/ufs/ufs.pas @@ -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); diff --git a/sys/fs/ufs/ufs_vnops.pas b/sys/fs/ufs/ufs_vnops.pas index a4f0fb09..e3fda311 100644 --- a/sys/fs/ufs/ufs_vnops.pas +++ b/sys/fs/ufs/ufs_vnops.pas @@ -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; diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index 93fcd44d..a92f4a19 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -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 diff --git a/sys/vfs/vfs_syscalls.pas b/sys/vfs/vfs_syscalls.pas index 71659d42..2a60b974 100644 --- a/sys/vfs/vfs_syscalls.pas +++ b/sys/vfs/vfs_syscalls.pas @@ -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 diff --git a/sys/vfs/vnode.pas b/sys/vfs/vnode.pas index c584ae61..e164e585 100644 --- a/sys/vfs/vnode.pas +++ b/sys/vfs/vnode.pas @@ -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