windows-pcache-20050310
authorJeffrey Altman <jaltman@sinenomine.net>
Fri, 11 Mar 2005 05:33:12 +0000 (05:33 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 11 Mar 2005 05:33:12 +0000 (05:33 +0000)
This patch applies all of the work done to add persistent cache support,
cache manager debugging, and a variety of bug fixes.  A full description
will be committed within doc/txt/winnotes as part of a later commit.

355 files changed:
doc/txt/winnotes/afs-changes-since-1.2.txt
doc/txt/winnotes/afs-install-notes.txt
doc/txt/winnotes/afs-integration.txt [new file with mode: 0644]
doc/txt/winnotes/msi-deployment-guide.txt
doc/txt/winnotes/performance.txt [new file with mode: 0644]
doc/txt/winnotes/registry.txt
src/WINNT/afsadmsvr/.cvsignore [new file with mode: 0644]
src/WINNT/afsapplib/.cvsignore [new file with mode: 0644]
src/WINNT/afsapplib/NTMakefile
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_eventlog.c
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/afsd_init95.c
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/afsd_service.rc
src/WINNT/afsd/afsdacl.c [new file with mode: 0644]
src/WINNT/afsd/afsdacl.rc [new file with mode: 0644]
src/WINNT/afsd/afskfw.c
src/WINNT/afsd/afslogon.c
src/WINNT/afsd/afslogon.h
src/WINNT/afsd/afsshare.c
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_access.c
src/WINNT/afsd/cm_aclent.c
src/WINNT/afsd/cm_aclent.h
src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_buf.h
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_callback.h
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_cell.h
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_config.h
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_daemon.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dcache.h
src/WINNT/afsd/cm_diskcache95.c
src/WINNT/afsd/cm_dnlc.c
src/WINNT/afsd/cm_dnlc.h
src/WINNT/afsd/cm_freelance.c
src/WINNT/afsd/cm_freelance.h
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_memmap.c [new file with mode: 0644]
src/WINNT/afsd/cm_memmap.h [new file with mode: 0644]
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h
src/WINNT/afsd/cm_utils.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_vnodeops.h
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h
src/WINNT/afsd/cmdebug.c [new file with mode: 0644]
src/WINNT/afsd/cmdebug.rc [new file with mode: 0644]
src/WINNT/afsd/fs.c
src/WINNT/afsd/fs_utils.c
src/WINNT/afsd/lanahelper.cpp
src/WINNT/afsd/lanahelper.h
src/WINNT/afsd/libafsconf.def
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c
src/WINNT/afsd/smb3.h
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afslegal/lang/ja_JP/afslegal.rc
src/WINNT/afslegal/lang/ko_KR/afslegal.rc
src/WINNT/afsreg/NTMakefile
src/WINNT/afsreg/afsreg.h
src/WINNT/afsreg/syscfg.c
src/WINNT/afssvrcfg/.cvsignore [new file with mode: 0644]
src/WINNT/afssvrcfg/NTMakefile
src/WINNT/afssvrcfg/lang/.cvsignore [new file with mode: 0644]
src/WINNT/afssvrcfg/lang/de_DE/afscfg.rc
src/WINNT/afssvrcfg/lang/es_ES/afscfg.rc
src/WINNT/afssvrcfg/lang/ja_JP/afscfg.rc
src/WINNT/afssvrcfg/lang/ko_KR/afscfg.rc
src/WINNT/afssvrcfg/lang/pt_BR/afscfg.rc
src/WINNT/afssvrcfg/lang/zh_CN/afscfg.rc
src/WINNT/afssvrcfg/lang/zh_TW/afscfg.rc
src/WINNT/afssvrcpa/.cvsignore [new file with mode: 0644]
src/WINNT/afssvrcpa/NTMakefile
src/WINNT/afssvrcpa/cpl_interface.cpp
src/WINNT/afssvrcpa/lang/.cvsignore [new file with mode: 0644]
src/WINNT/afssvrcpa/lang/ja_JP/afssvrcpa.rc
src/WINNT/afssvrcpa/lang/pt_BR/afssvrcpa.rc
src/WINNT/afssvrmgr/NTMakefile
src/WINNT/afsusrmgr/.cvsignore [new file with mode: 0644]
src/WINNT/afsusrmgr/NTMakefile
src/WINNT/afsusrmgr/lang/.cvsignore [new file with mode: 0644]
src/WINNT/afsusrmgr/lang/de_DE/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/es_ES/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/ja_JP/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/ko_KR/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/pt_BR/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/zh_CN/AfsUsrMgr.rc
src/WINNT/afsusrmgr/lang/zh_TW/AfsUsrMgr.rc
src/WINNT/aklog/.cvsignore [new file with mode: 0644]
src/WINNT/aklog/aklog.c
src/WINNT/bosctlsvc/.cvsignore [new file with mode: 0644]
src/WINNT/client_config/.cvsignore [new file with mode: 0644]
src/WINNT/client_config/RegistrySupport.cpp
src/WINNT/client_config/afs_config.h
src/WINNT/client_config/afsmap.c [new file with mode: 0644]
src/WINNT/client_config/cellservdb.c
src/WINNT/client_config/config.cpp
src/WINNT/client_config/dlg_automap.cpp
src/WINNT/client_config/drivemap.cpp
src/WINNT/client_config/lang/.cvsignore [new file with mode: 0644]
src/WINNT/client_config/lang/de_DE/afs_config.rc
src/WINNT/client_config/lang/es_ES/afs_config.rc
src/WINNT/client_config/lang/ja_JP/afs_config.rc
src/WINNT/client_config/lang/ko_KR/afs_config.rc
src/WINNT/client_config/lang/pt_BR/afs_config.rc
src/WINNT/client_config/lang/zh_TW/afs_config.rc
src/WINNT/client_config/pagesize.cpp
src/WINNT/client_cpa/.cvsignore [new file with mode: 0644]
src/WINNT/client_cpa/cpl_interface.cpp
src/WINNT/client_cpa/lang/.cvsignore [new file with mode: 0644]
src/WINNT/client_cpa/lang/ja_JP/afs_cpa.rc
src/WINNT/client_creds/NTMakefile
src/WINNT/client_creds/advtab.cpp
src/WINNT/client_creds/afscreds.h
src/WINNT/client_creds/creds.cpp
src/WINNT/client_creds/main.cpp
src/WINNT/client_creds/misc.cpp
src/WINNT/client_creds/shortcut.cpp
src/WINNT/client_creds/window.cpp
src/WINNT/client_exp/shell_ext.cpp
src/WINNT/client_exp/submounts_dlg.cpp
src/WINNT/client_osi/osilog.c
src/WINNT/doc/help/de_DE/afs-cc.CNT
src/WINNT/doc/help/de_DE/afs-light.CNT
src/WINNT/doc/help/de_DE/afs-nt.CNT
src/WINNT/doc/help/de_DE/taafscfg.cnt
src/WINNT/doc/help/de_DE/taafssvrmgr.cnt
src/WINNT/doc/help/de_DE/taafsusrmgr.cnt
src/WINNT/doc/help/es_ES/AFS-CC.CNT
src/WINNT/doc/help/es_ES/AFS-NT.CNT
src/WINNT/doc/help/es_ES/TAAFSCFG.CNT
src/WINNT/doc/help/es_ES/afs-light.cnt
src/WINNT/doc/help/es_ES/taafssvrmgr.CNT
src/WINNT/doc/help/ja_JP/afs-cc.CNT
src/WINNT/doc/help/ja_JP/afs-light.CNT
src/WINNT/doc/help/ja_JP/afs-nt.CNT
src/WINNT/doc/help/ja_JP/taafscfg.cnt
src/WINNT/doc/help/ja_JP/taafssvrmgr.cnt
src/WINNT/doc/help/ja_JP/taafsusrmgr.cnt
src/WINNT/doc/help/ko_KR/afs-cc.CNT
src/WINNT/doc/help/ko_KR/afs-light.CNT
src/WINNT/doc/help/ko_KR/afs-nt.CNT
src/WINNT/doc/help/ko_KR/taafscfg.cnt
src/WINNT/doc/help/ko_KR/taafssvrmgr.cnt
src/WINNT/doc/help/ko_KR/taafsusrmgr.cnt
src/WINNT/doc/help/pt_BR/afs-cc.CNT
src/WINNT/doc/help/pt_BR/afs-light.CNT
src/WINNT/doc/help/pt_BR/afs-nt.CNT
src/WINNT/doc/help/pt_BR/taafscfg.cnt
src/WINNT/doc/help/pt_BR/taafssvrmgr.cnt
src/WINNT/doc/help/pt_BR/taafsusrmgr.cnt
src/WINNT/doc/help/zh_CN/afs-cc.CNT
src/WINNT/doc/help/zh_CN/afs-light.CNT
src/WINNT/doc/help/zh_CN/afs-nt.CNT
src/WINNT/doc/help/zh_CN/taafscfg.cnt
src/WINNT/doc/help/zh_CN/taafssvrmgr.cnt
src/WINNT/doc/help/zh_CN/taafsusrmgr.cnt
src/WINNT/doc/help/zh_TW/afs-cc.CNT
src/WINNT/doc/help/zh_TW/afs-light.CNT
src/WINNT/doc/help/zh_TW/afs-nt.CNT
src/WINNT/doc/help/zh_TW/taafscfg.cnt
src/WINNT/doc/help/zh_TW/taafssvrmgr.cnt
src/WINNT/doc/help/zh_TW/taafsusrmgr.cnt
src/WINNT/doc/install/Documentation/de_DE/README.txt
src/WINNT/doc/install/Documentation/de_DE/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/de_DE/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/de_DE/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/de_DE/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/de_DE/html/index.htm
src/WINNT/doc/install/Documentation/en_US/README.txt
src/WINNT/doc/install/Documentation/en_US/html/CmdRef/auarf260.htm
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/cachmgr.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/fserver1.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/fserver2.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/overview.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/scout1.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/scout2.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/scout3.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/scout4.gif
src/WINNT/doc/install/Documentation/en_US/html/SysAdminGd/vnode.gif
src/WINNT/doc/install/Documentation/en_US/html/index.htm
src/WINNT/doc/install/Documentation/es_ES/README.txt
src/WINNT/doc/install/Documentation/es_ES/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/es_ES/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/es_ES/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/es_ES/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/es_ES/html/index.htm
src/WINNT/doc/install/Documentation/ja_JP/README.txt
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd000.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd002.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd003.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd004.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd005.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd006.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd007.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd008.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd009.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd010.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd011.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd012.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd013.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd014.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd015.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd016.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd017.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd018.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd019.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd020.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd021.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd022.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd023.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd024.htm
src/WINNT/doc/install/Documentation/ja_JP/html/SysAdminGd/auagd025.htm
src/WINNT/doc/install/Documentation/ja_JP/html/index.htm
src/WINNT/doc/install/Documentation/ko_KR/README.txt
src/WINNT/doc/install/Documentation/ko_KR/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/ko_KR/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/ko_KR/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/ko_KR/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns000.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns002.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns003.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns004.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns005.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns006.htm
src/WINNT/doc/install/Documentation/ko_KR/html/ReleaseNotes/awrns007.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd000.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd002.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd003.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd004.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd005.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd006.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd007.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd008.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd009.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd010.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd011.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd012.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd013.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd014.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd015.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd016.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd017.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd018.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd019.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd020.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd021.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd022.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd023.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd024.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd025.htm
src/WINNT/doc/install/Documentation/ko_KR/html/SysAdminGd/auagd026.htm
src/WINNT/doc/install/Documentation/ko_KR/html/index.htm
src/WINNT/doc/install/Documentation/pt_BR/README.txt
src/WINNT/doc/install/Documentation/pt_BR/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/pt_BR/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/pt_BR/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/pt_BR/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns000.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns002.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns003.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns004.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns005.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns006.htm
src/WINNT/doc/install/Documentation/pt_BR/html/ReleaseNotes/awrns007.htm
src/WINNT/doc/install/Documentation/pt_BR/html/index.htm
src/WINNT/doc/install/Documentation/zh_CN/README.txt
src/WINNT/doc/install/Documentation/zh_CN/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/zh_CN/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/zh_CN/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/zh_CN/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/zh_CN/html/index.htm
src/WINNT/doc/install/Documentation/zh_TW/README.txt
src/WINNT/doc/install/Documentation/zh_TW/html/InstallGd/awqbg000.htm
src/WINNT/doc/install/Documentation/zh_TW/html/InstallGd/awqbg002.htm
src/WINNT/doc/install/Documentation/zh_TW/html/InstallGd/awqbg003.htm
src/WINNT/doc/install/Documentation/zh_TW/html/InstallGd/awqbg004.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns000.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns002.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns003.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns004.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns005.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns006.htm
src/WINNT/doc/install/Documentation/zh_TW/html/ReleaseNotes/awrns007.htm
src/WINNT/doc/install/Documentation/zh_TW/html/index.htm
src/WINNT/install/InstallShield5/GenFileGroups.bat
src/WINNT/install/InstallShield5/lang/de_DE/value.shl
src/WINNT/install/InstallShield5/lang/es_ES/value.shl
src/WINNT/install/InstallShield5/lang/ja_JP/value.shl
src/WINNT/install/InstallShield5/lang/ko_KR/value.shl
src/WINNT/install/InstallShield5/lang/pt_BR/value.shl
src/WINNT/install/InstallShield5/lang/zh_CN/value.shl
src/WINNT/install/InstallShield5/lang/zh_TW/value.shl
src/WINNT/install/NSIS/AdminGroup.cpp
src/WINNT/install/NSIS/CellServDB
src/WINNT/install/NSIS/OpenAFS.nsi
src/WINNT/install/Win9x/CellServDB
src/WINNT/install/Win9x/RUNONCE.PIF
src/WINNT/install/Win9x/ReadMe.rtf
src/WINNT/install/wix/CellServDB
src/WINNT/install/wix/afsdesktop.ini [new file with mode: 0644]
src/WINNT/install/wix/custom/afscustom.cpp
src/WINNT/install/wix/feature.wxi
src/WINNT/install/wix/files.wxi
src/WINNT/license/lang/de_DE.ide
src/WINNT/license/lang/en_US.ide
src/WINNT/license/lang/es_ES.ide
src/WINNT/license/lang/ja_JP.ide
src/WINNT/license/lang/ko_KR.ide
src/WINNT/license/lang/pt_BR.ide
src/WINNT/license/lang/zh_CN.ide
src/WINNT/license/lang/zh_TW.ide
src/WINNT/pthread/pthread.c
src/WINNT/pthread/test/native.cpp
src/WINNT/talocale/tal_alloc.cpp
src/WINNT/win9xpanel/CellServDB
src/WINNT/win9xpanel/Help/PROPER.MRB
src/afsinstall/lib/InstallGuides/GENERIC/clientconfig
src/bozo/NTMakefile
src/bucoord/NTMakefile
src/budb/NTMakefile
src/butc/NTMakefile
src/config/NTMakefile.amd64_w2k [new file with mode: 0644]
src/config/NTMakefile.i386_nt40
src/config/NTMakefile.i386_w2k [new file with mode: 0644]
src/config/afs_sysnames.h
src/config/afsconfig-windows.h
src/kauth/NTMakefile
src/libafsrpc/NTMakefile
src/libafsrpc/afsrpc.def
src/ptserver/NTMakefile
src/rx/NTMakefile
src/rx/rx.c
src/rx/rx_packet.c
src/rx/rx_user.c
src/rxkad/rxkad_common.c
src/sys/pioctl_nt.c
src/ubik/NTMakefile
src/update/NTMakefile
src/viced/callback.c
src/vlserver/NTMakefile
src/volser/NTMakefile

index b40e670..f61977e 100644 (file)
@@ -1,7 +1,87 @@
 Since 1.3.77:
-  * The list of ACL entries was becoming corrupted because the function
-    which obtained a free entry was doing so without the appropriate lock
-    being held.
+  * The allDown logic in cm_ConnByMServers() was wrong.  The allDown
+    flag should not be cleared if a volume's server reference is 
+    marked as "offline".  In the case where all of the volume's 
+    servers are either "down" or the volumes are "offline", we want
+    cm_Analyze() to process the condition as CM_ERROR_ALLOFFLINE
+    instead of as CM_ERROR_TIMEDOUT.  In fact, CM_ERROR_TIMEDOUT
+    should never occur in practice.
+
+    In the case of CM_ERROR_ALLOFFLINE, cm_Analyze() will sleep for
+    5 seconds, clear the server down and volume busy flags, and 
+    then force an update from the VLDB.  This allows the client to 
+    update the location of a volume if the reason for it being 
+    marked offline is because it is being moved.  Calls to 
+    cm_ConnByMServers() will be retried either until success or
+    the RDRtimeout period is reached.
+
+  * Correct the Power Management code behavior in response to 
+    Standby, Suspend, and Shutdown events.  Instead of flushing the
+    buffers associated with the mounted SMB submounts, simply write
+    all buffers which are marked dirty.
+
+  * Added support for "TheseCells" to afslogon.dll.  "TheseCells"
+    provides a list of cells other than the default cell for which
+    tokens should be obtained using the default Kerberos principal.
+    This functionality is logon domain specific and is only available
+    when using KFW for authentication.
+
+  * Fixed FindNext Invalid Handle error caused by over agressive 
+    attempts at garbage collecting dirSearch entries when the 
+    dirSearch ID wraps from the maximum value to 1.
+
+  * Add support for registry defined server preferences for VLDB and 
+    File servers.  See registry.txt for details.
+
+  * Increased default cache size to 96MB and default number of cache
+    entries to 10,000.
+
+  * Fixed refCount leaks related to directory lookups and pioctl calls.
+
+  * Callbacks revoked during a race condition with an attempt to 
+    obtain the same callback no longer result in an inaccessible
+    stat cache entry.
+
+  * New command line tool:
+
+        afsdacl : Set or reset the DACL to allow starting or stopping
+             the afsd service by any ordinary user.
+
+        Usage : afsdacl [-set | -reset] [-show]
+              -set   : Sets the DACL
+              -reset : Reset the DACL
+              -show  : Show current DACL (SDSF)
+
+  * IP addresses are no longer queried once at startup.  Instead IP
+    addresses are obtained as needed.   Loopback adapter addresses are
+    no longer published to the server.
+
+  * Pay attention to the MIT KFW registry configuration for automatic
+    importation of MSLSA credentials. (SOFTWARE\MIT\Leash32,MsLsaImport)
+
+  * Fix (once again) case-sensitive comparisons which was apparently 
+    broken in 1.3.72.
+
+  * Activate support for vos listvol -format
+
+  * Population of the "AFS Client Admins" group failed on non-English
+    versions of Windows because the name of the "Administrators" group
+    is localized.  Now we lookup the name of the group by using the
+    Administrators Group Alias Relative ID.
+
+  * Multiple cell token acquisition within afscreds.exe was broken in the 
+    case of Kerberos 5 cross realm authentication.  Instead of contacting
+    the KDC associated with the cell's realm, afscreds would obtain a 
+    token from the KDC of the user's realm.  This would result in
+    "invalid kvno errors" while authenticating to the AFS servers.  
+    Unauthenticated access would work.  The symptoms would vary based upon
+    whether or not the VLDB servers had been contacted using unauthenticated
+    connections prior to the user obtaining tokens.
+
+  * The list of ACL entries was becoming corrupted.  It appears as if 
+    an ACL when it expires was not being appropriately cleaned up.  In
+    fact, it was left in the list of ACLs associated with the scache 
+    entry.
 
   * Changed the default @sys name list to "x86_win32 i386_w2k i386_nt40"
     for 32-bit x86 systems.  The default for itanium will be "ia64_win64"
@@ -18,11 +98,47 @@ Since 1.3.77:
     STATUS_NOT_A_DIRECTORY instead of the expected 
     STATUS_OBJECT_PATH_NOT_FOUND.  This would cause the Windows SMB client
     to terminate the search for the DLL causing the execution of the 
-    application to fail.                                                                           
+    application to fail.
 
-  * Re-work the reference counting of smb_vc_t objects.  The references
+  * Rework the reference counting of smb_vc_t objects.  The references  
     stored in the waiting locks were not counted.  This could result in
-    an assertion if the reference count drops below 0.
+    an assertion if the reference count drops to zero.
+
+  * "fs wscell" returns "Freelance.Local.Root" for the workstation cell
+    when running in freelance mode.
+
+  * Added support for persistent caching of file contents, stat entries,
+    volume data, cell data, and name lookup data.  When the registry 
+    value, "NonPersistentCaching", is not defined or set to 0 the file 
+    specified by "CachePath" becomes a persistent cache file.   The 
+    size of the cache file is computed at run time.  It has a maximum
+    size of approximately 1.2GB.  The contents of the file will be 
+    validated according to the rules specified by the "ValidateCache"
+    registry value.  
+
+  * Added support for UUIDs.  UUIDs are kept for as long as the 
+    cache file is intact.
+
+  * Added cmdebug.exe and support cache manager debugging callback 
+    interfaces in afsd_service.exe.
+
+    Usage: cmdebug -servers <server machine> [-port <IP port>] [-long] 
+                   [-addrs] [-cache] [-help]
+    Where: -long   print all info
+           -addrs  print only host interfaces
+           -cache  print only cache configuration
+
+  * Symlinks to \\AFS\[all\]... will now be treated the same as 
+    symlinks to /afs/....   However, please use /afs/... as otherwise
+    the symlinks won't work on Unix.
+  
+  * Correct a problem with local CellID allocation for cells whose 
+    server list is obtained via DNS instead of a CellServDB file.  If
+    the DNS information expires the CellID assigned to the entry will
+    be changed.  This causes all of the cm_scache_t objects which refer
+    to the old cellID number to become useless.  Attempts to access 
+    files or directories with cm_scache_t objects using the old cellID
+    will fail since the server list cannot be obtained.
 
   * Correct deadlock condition in cm_EndCallbackGrantingCall which can
     be triggered if the volume referenced by the cm_scache_t object is
index d70ee0d..1ec3a34 100644 (file)
@@ -11,6 +11,8 @@ The 1.3.x series of releases not only fixes a large number of bugs in the 1.2
 series but also attempts to enhance the functionality of the product to better 
 fit the usage model of today's users.  Several items standout.  
 
+0. The default AFSCache file is approximately 100MB.  This space is required 
+in addition to the space allocated to OpenAFS binaries.
 
 1. The Kerberos 4 infrastructure on which the 1.2 series is reliant is no 
 longer secure.  Cross-realm Kerberos is very important in the AFS context and 
diff --git a/doc/txt/winnotes/afs-integration.txt b/doc/txt/winnotes/afs-integration.txt
new file mode 100644 (file)
index 0000000..fb6d056
--- /dev/null
@@ -0,0 +1,200 @@
+How to determine if OpenAFS is installed?
+
+When the OpenAFS Client Service is installed there will be several 
+registry keys created:
+
+  HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon
+     "ImagePath" = "path to afsd_service.exe"
+
+  HKLM\SOFTWARE\TransarcCorporation\AFS Client\CurrentVersion
+     "PathName" = "the path to the client installation directory"
+     "MajorVersion" 
+     "MinorVersion"
+     "VersionString"
+
+BOOL IsAFSServerInstalled (void)
+{
+   BOOL fInstalled = FALSE;
+   TCHAR szKey[] = TEXT("HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon");
+   LPCTSTR pch = lstrchr (szKey, TEXT('\\'));
+   HKEY hk;
+   
+   if (RegOpenKey (HKEY_LOCAL_MACHINE, &pch[1], &hk) == 0)
+   {
+      fInstalled = TRUE;
+      RegCloseKey (hk);
+   }
+
+   return fInstalled;
+}
+
+How to determine if OpenAFS is active?
+
+The AFS Client Service is normally started automatically at system boot.
+The state of the service may be queried by asking the Windows Service 
+Manager.
+
+BOOL IsAFSServiceRunning (void)
+{
+    SERVICE_STATUS Status;
+    memset (&Status, 0x00, sizeof(Status));
+    Status.dwCurrentState = SERVICE_STOPPED;
+
+    SC_HANDLE hManager;
+    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
+    {
+        SC_HANDLE hService;
+        if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
+        {
+            QueryServiceStatus (hService, &Status);
+            CloseServiceHandle (hService);
+        }
+        CloseServiceHandle (hManager);
+    }
+    return (Status.dwCurrentState == SERVICE_RUNNING);
+}
+
+How to determine the AFS UNC Service Name?
+
+The local UNC service name registered by the OpenAFS Client Service SMB/CIFS 
+Server depends on whether or not a Microsoft Loopback Adapter has been 
+installed and the contents of a registry value.  The loopback adapter is 
+important because if the service cannot bind itself to a loopback adapter 
+then the registered SMB/CIFS service name must be unique to the WINS name
+space.  When the loopback adapter is installed, a globally common name such
+as "AFS" can be used.
+
+If the loopback adapter is installed the UNC server name will be the value at:
+
+  HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters
+    REG_SZ/REG_EXPAND_SZ  "NetbiosName"
+
+If this value is not present, the default is "AFS".
+
+When the loopback adapter is not installed the UNC name will be:
+
+  %COMPUTERNAME%-%NetbiosName%
+
+if the Computer Name is "MYHOST" and the Netbios Name is "AFS" then
+the UNC server name will be: 
+
+  MYHOST-AFS
+
+At the moment there is no readily available code exported by a library to 
+determine if the loopback adapter is installed or not.  What I will do if
+someone requests it is add a new AFS pioctl operation which will return
+the in use UNC Server Name.
+
+
+How to determine the AFS unix mount point path?
+
+On Unix systems the local mount point of the AFS file system is usually "/afs".
+Some organizations have their own custom local mount point locations.  To 
+determine what the locally configured unix mount point is for interpretting
+Unix style paths there is a registry value:
+
+  HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters
+    REG_SZ "MountRoot"
+
+If this value does not exist the default value is "/afs".
+
+What are AFS pioctl() operations and how do I call them?
+
+AFS pioctl() operations are IPCs which can be used to communicate with the
+AFS Client Service for the purposes of querying or changing the state of
+the service.
+
+The pioctl() function has a prototype of:
+
+struct ViceIoctl {
+    long in_size;
+    long out_size;
+    void *in;
+    void *out;
+};
+
+long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow);
+
+and can be loaded from the library "afsauthent.dll" at runtime.  The default
+calling convention is used.
+
+
+How to test to see if a PATH is within AFS?
+
+Given an arbitrary file path, you can test to see if the path is in the AFS
+file system with the following function.  It asks the AFS Client Service to 
+return the name of the cell in which the path exists.  If the cell name cannot
+be found, the path is not in the AFS file space.
+
+BOOL IsPathInAFS(const CHAR *strPath)
+{
+    struct ViceIoctl blob;
+    char cellname[256];
+    int code;
+
+    blob.in_size = 0;
+    blob.out_size = sizeof(cellname);
+    blob.out = cellname;
+
+    code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
+    if (code)
+        return FALSE;
+    return TRUE;
+}
+
+
+What are AFS cells, volumes and mount points?
+
+The AFS file system consists of a series of administrative domains called 
+"cells" each of which contain two or more volumes.  A volume is a file system
+unit which contains files, directories, mount points, symlinks and hard
+links.
+
+Each cell has a minimum of two volumes.  When an AFS client connects to a 
+cell it mounts the cell's "root.afs" volume at the local afs mount point path.
+Each "root.afs" volume contains one or more mount points which allow the 
+AFS client to other volumes in both in the current cell as well as other 
+cells.  There are two types of mount points: read-only and read-write.  
+By following a read-only mount point the client can obtain data from any
+of the equivalent read-only volume replicas.  By following a read-write mount
+point the client is restricted to the one and only read-write copy of the
+volume.  Periodically replicated volumes have their read-write copy "released"
+which results in a synchronization with the read-only copies.
+
+By convention the first volume of every cell to contain real data is called 
+"root.cell".  The name of the read-only mount point which joins the "root.afs"
+volume to the "root.cell" volume is the name of the cell.  The name of the 
+read-write mount point is the name of the cell prefaced by a dot.  For 
+example, the "athena.mit.edu" cell's "root.afs" volume will contain mount points
+such as
+
+        "athena.mit.edu"  -> "#athena.mit.edu:root.cell" 
+        ".athena.mit.edu" -> "%athena.mit.edu:root.cell" 
+
+The '#' indicates a read-only mount point and the '%' indicates a read-write 
+mount point.  The mount points are not limited to the local cell so additional 
+mount points might be included such as:
+
+        "andrew.cmu.edu" -> "#andrew.cmu.edu:root.cell" 
+        "sipb.mit.edu"   -> "#sipb.mit.edu:root.cell"
+
+The mount points appear as directory entries to the operating system.
+
+Volumes can also store files, hard links to files, and symlinks to files.  
+
+On Windows, hardlinks can be created and destroyed using the CreateHardLink() 
+and DeleteFile() Win32 APIs.  
+
+Creating, Listing and Destroying symlinks and mount points is performed by
+the user via the OpenAFS provided command line tools: fs.exe and symlink.exe.
+  symlink make <name> <to>
+  symlink list <name>
+  symlink rm <name>
+
+  fs mkmount <dir> <vol> [<cell>] [-rw]
+  fs lsmount <dir>+
+  fs rmmount <dir>+
+
+These operations are performed via pioctl calls. 
+
index 2ee9046..c833dc8 100644 (file)
@@ -6,14 +6,15 @@ OpenAFS for Windows
      Contents
 
      1.  Introduction
-     1.1 Requirements
+     1.1   Requirements
 
      2.         Configuration options
-     2.1 Configurable properties
-     2.2 Existing registry values
+     2.1   Configurable properties
+     2.2   Existing registry values
+     2.3   Replacing Configuration Files
+     2.4   Adding Domain Specific Registry Keys
 
      3.         Additional resources
-     3.1 Example
 
      4.         Upgrades
 
@@ -30,12 +31,12 @@ OpenAFS for Windows
     to deploy OpenAFS through Group Policy.
 
     This document provides a guide for authoring transforms used to
-    customize the MSI package for a particular organization.
-    Although many settings can be deployed via transforms, in an
-    Active Directory environment it is advisable to deploy registry
-    settings and configuration files through group policy and/or
-    startup scripts so that machines where OpenAFS for Windows is
-    already installed will pick up these customizations.
+    customize the MSI package for a particular organization.  Although 
+    many settings can be deployed via transforms, in an Active 
+    Directory environment it is advisable to deploy registry settings
+    and configuration files through group policy and/or startup 
+    scripts so that machines where OpenAFS for Windows is already
+    installed will pick up these customizations.
 
 1.1 Requirements
 
@@ -45,37 +46,123 @@ OpenAFS for Windows
     releases. Not all releases support all the configuration options
     documented here.
 
-    Authoring a Windows Installer transform requires additional
+    Authoring a "Windows Installer" transform requires additional
     software for editing the MSI database tables and generating the
     transform from the modified MSI package.  ORCA.EXE and MSITRAN.EXE
-    which are included in the Windows Platform SDK (Windows Installer
+    which are included in the Windows Platform SDK ("Windows Installer"
     SDK) can be used for this purpose.
 
-    The schema for the MSI package is based on SCHEMA.MSI distributed
-    with the Platform SDK.
+    For reference, the schema for the MSI package is based on
+    SCHEMA.MSI distributed with the Platform SDK.
+
+    For general information about "Windows Installer", refer to :
+
+    http://msdn.microsoft.com/library/en-us/msi/setup/windows_installer_start_page.asp
+
+    For general information about authoring MSI transforms, refer to :
+
+    http://msdn.microsoft.com/library/en-us/msi/setup/transforms.asp
+
+    The remainder of this document assumes some familiarity with
+    authoring transforms.  While the MSDN documentation for Windows
+    Installer is a bit dense, it is recommended that you read through
+    the guide on MSI transforms found at the second link above.  Also
+    MSDN includes a step-by-step example for creating a transform at:
+
+    http://msdn.microsoft.com/library/en-us/msi/setup/a_customization_transform_example.asp
+
+1.2  Authoring a Transform
+
+    Transforms describe a set of modifications to be performed on an
+    existing MSI for the purpose of customizing it.  This is
+    ordinarily done by making a copy of the MSI to be customized,
+    modifying the copy and then using the old and the new MSI to
+    generate a transform.
+
+    E.g:
+       > copy openafs.msi openafs-modified.msi
+       
+       (edit the openafs-modified.msi to include the necessary changes)
+
+       > msitran -g openafs-modified.msi openafs.msi openafs-transform.mst
+
+       (generates openafs-transform.mst, which is the transform)
+
+    Transforms have an extension of .mst.  'msitran' is a tool
+    distributed as part of the "Windows Installer" SDK (which in turn is
+    a part of the Windows Platform SDK).
+
+    You can test a transform by :
+
+       > copy openafs.msi openafs-test.msi
+       > msitran -a openafs-transform.mst openafs-test.msi
+
+    and then checking the resulting openafs-test.msi to see if all the
+    changes you have made above to openafs-modified.msi is present in
+    openafs-test.msi.  'msitran' will complain if some modification in the
+    transform can not be successfully applied.
+
+    As mentioned above, you can use a tool like ORCA.EXE to edit the
+    MSI databases directly when editing openafs-modified.msi.  More
+    details are given below.
 
 ----------------------------------------------------------------------
 
 2.  Configuration Options
 
+    The logic necessary to implement many of the settings described in
+    the registry.txt file are present in the MSI.  Most of these can be
+    controlled by setting the corresponding properties to the desired
+    value.  Some settings may require modifying existing registry
+    entries (though not recommended) or adding new resources (like
+    files or registry keys).  Instructions for performing these tasks
+    are below.
+
 2.1 Configurable Properties
 
-    Most configurable properties correspond to registry keys or values.
-    To avoid duplication, only a reference to the relevant registry key
-    or value is given here.  For more details about the associated
-    semantics, please refer to registry.txt distributed with the
-    OpenAFS for Windows release.
+    Most configurable properties correspond to registry keys or
+    values.  Please refer to the release notes for more information
+    about how these registry settings are used.
+
+    Due to the logic invoked based on the existence of these registry
+    keys or values, they are only set if the associated property is
+    defined to have a non null value.  If the associated property is
+    not defined in the MSI, the registry key or value will not be
+    touched.  By default, the MSI does not contain these properties
+    and hence will not set the registry keys.  You will need to add
+    properties as needed to the MSI.
 
-    These properties are, of course, found in the 'Property' table of
-    the MSI package.
+    When one of the configurable properties is set, the installer will
+    use the property value to set the corresponding setting in the
+    HKEY_LOCAL_MACHINE registry hive.  HKEY_CURRENT_USER hive is not
+    touched by the installer.
 
-    For brevity the following nomenclature will be used to refer to
-    registry keys:
+    For each property, the associated registry setting is referenced
+    by the same text used in the registry.txt file.
 
     Strings are quoted using single quotes (e.g. 'a string'). An empty
     string is denoted as ''.  Note that you can't author null values
-    into the 'Property' table.  To achieve this effect you'll have to
-    drop the relevant row.
+    into the 'Property' table.
+
+    Numeric values should be authored as decimal strings.
+
+2.1.1  Setting Properties
+
+    In order to set a property,
+
+    a.  Open the MSI in ORCA.EXE
+
+    b.  Select the 'Property' table from the list of tables on the left.
+
+    c.  Find the property in the list of properties on the right,
+        double click the value and type the new value.
+
+    d.  If the property does not exist in the property list, right
+        click the list and select 'Add Row', type the property name
+        and the desired value.
+
+
+2.1.2   OpenAFS for Windows properties
 
     (Service parameters):
     [HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters]
@@ -235,29 +322,159 @@ OpenAFS for Windows
     column in the 'Registry' table.  If you want to add additional
     registry keys please refer to section 3 (Additional Resources).
 
-----------------------------------------------------------------------
+2.3 Replacing Configuration Files
 
-3   Additional Resources
+    The OpenAFS configuration files (CellServDB)
+    can be replaced by your own configuration files.  These files are
+    contained in separate MSI components so that you can disable them
+    individually.
 
-    If you want to add registry keys or files you need to create new
-    components and features for those.  Refer to the Windows Platform
-    SDK for details.
+    The recommended method for replacing these files is to first
+    disable the components containing the configuration files that you
+    want to replace, and then add new components for the replacement
+    files.  This is outlined below (assuming you are using ORCA.EXE to
+    author the transform).
 
-    Add new features under the 'feaClient' or 'feaServer' as
-    appropriate and set the 'Level' column for those features to equal
-    the 'Level' for their parent features for consistency.  Note that
-    none of the features in the OpenAFS for Windows MSI package are
-    designed to be installed to run from 'source' or 'advertised'.  It
-    is recommended that you set 'msidbFeatureAttributesFavorLocal' (0),
-    'msidbFeatureAttributesFollowParent' (2) and
-    'msidbFeatureAttributesDisallowAdvertise' (8) attributes for new
-    features.
+    Note that transforms are not a good way to add a new file as an
+    embedded stream.  The method outlined here places the file in the
+    same directory as the MSI for deployment.
 
-    If you are creating new components, retain the same component GUID
-    when creating new transforms against new releases of the OpenAFS
-    MSI package.
+    The walkthrough below is to add a custom 'CellServDB' file.
+
+    1) Disable the component that contains the configuration file that
+       you want to replace.
+
+       1.1) Locate and select the 'Component' table in the 'Tables'
+            list.
+
+       1.2) In the Component table, locate the component you need to
+            change ( Ctrl-F invokes the 'Find' dialog).  The component
+            names are listed below in section 2.3.1.  For this
+            example, the component name is 'elf_CellServDB'.
+
+       1.3) Go to the 'Condition' column of the component.
+
+       1.4) Enter a condition that evaluates to
+            false. I.e. 'DONOTINSTALL'. (Note that an undefined
+            property always evaluates to false).
+
+       Note that you can also use this step to disable other
+       configuration files without providing replacements.
+
+    2) Add a new component containing the new configuration file.
+
+       2.1) Select the 'Component' table in the 'Tables' list.
+
+       2.2) Select 'Tables'->'Add Row' (Ctrl-R).
+
+       2.3) Enter the following :
 
-3.1 Example: Adding domain specific registry keys
+            Component     : cmf_my_CellServDB
+           ComponentId   : {7019836F-BB2C-4AF6-9463-0D6EC9035CF1}
+           Directory_    : dirClient
+           Attributes    : 144
+           Condition     :
+           KeyPath       : fil_my_CellServDB
+
+           Note that the ComponentId is an uppercase GUID.  You can
+           generate one using GUIDGEN.EXE or UUIDGEN.EXE, both of
+           which are included in the Platform SDK.
+
+           The Attributes value of 144 is a sum of
+           msidbComponentAttributesPermanent (16) and
+           msidbComponentAttributesNeverOverwrite (128).  This
+           ensures that local modifications are not overwritten or
+           lost during an installation or uninstallation.  These are
+           the same settings used on the default configuration files.
+
+           'fil_my_CellServDB' is a key into the 'File' table which we
+           will fill later.
+
+    3) Add a new feature to hold the new component.
+
+       3.1) Select the 'Feature' table.
+
+       3.2) Add a new row (Ctrl-R or 'Tables'->'Add Row') with the
+            following values:
+
+           Feature       : fea_my_CellServDB
+           Feature_Parent: feaClient
+           Title         :
+           Description   :
+           Display       : 0
+           Level         : 30
+           Directory_    :
+           Attributes    : 8
+
+           It is important to create the new feature under the
+           'feaClient' feature, which will ensure that the
+           configuration file will be installed when the client
+           binaries are installed.
+
+           Setting 'Display' to 0 will hide this feature from the
+           feature selection dialog during an interactive
+           installation.  A value of 30 for 'Level' allows this
+           feature to be installed by default (on a 'Typical'
+           installation).
+
+           The 'Attributes' value is
+           msidbFeatureAttributesDisallowAdvertise (8), which is set
+           on all features in the OpenAFS MSI.  The OpenAFS MSI is not
+           designed for an advertised installation.
+
+    4) Join the component and the feature.
+
+       4.1) Select the 'FeatureComponents' table.
+
+       4.2) Add a new row with the following values:
+
+           Feature    : fea_my_CellServDB
+           Component  : cmf_my_CellServDB
+
+    5) Add an entry to the 'File' table.
+
+       5.1) Select the 'File' table.
+
+       5.2) Add a new row with the following values:
+
+           File        : fil_my_CellServDB
+           Component_  : cmf_my_CellServDB
+           FileName    : CellServDB
+           FileSize    : (enter file size here)
+           ...
+           Attributes  : 8192
+           Sequence    : 1000
+           (leave other fields blank)
+
+           The 'Attributes' value is msidbFileAttributesNonCompressed
+           (8192).  This is because we will be placing this file in
+           the same directory as the MSI instead of embedding the
+           file in it.  Transforms do not support updating compressed
+           sources or adding new cabinet streams.
+
+           Finally, the 'Sequence' value of 1000 will be used later
+           to distinguish the file as being in a separate source
+           location than the other files in the MSI.
+
+    6) Set a media source for the file.
+
+       6.1) Select the 'Media' table.
+
+       6.2) Add a row with the following values :
+
+           DiskId       : 2
+           LastSequence : 1000
+           ...
+           (leave other fields blank)
+
+           The sequence number of 1000 designates this as the media
+           source for the newly added file.
+
+2.3.1 Components for Configuration Files
+
+      CellServDB : 'cpf_CellServDB' (ID {D5BA4C15-DBEC-4292-91FC-B54C30F24F2A})
+
+2.4 Adding Domain Specific Registry Keys
 
     Following is an example for adding domain specific registry keys.
     Refer to section 2.1 in REGISTRY.TXT for more information.
@@ -347,6 +564,38 @@ OpenAFS for Windows
     integrated logon) and 'LOCALHOST' (disable integrated logon and
     fail logins silently).
 
+----------------------------------------------------------------------
+
+3   Additional Resources
+
+    If you want to add registry keys or files you need to create new
+    components and features for those.  Refer to the Windows Platform
+    SDK for details.
+
+    It is beyond the scope of this document to provide a comprehensive
+    overview of how to add new resources through a transform.  Please
+    refer to the "Windows Installer" documentation for details.  The
+    relevant section is at :
+
+    http://msdn.microsoft.com/library/en-us/msi/setup/using_transforms_to_add_resources.asp
+
+    A sample walkthrough of adding a new configuration file is in
+    section 2.3.
+
+    Add new features under the 'feaClient' or 'feaServer' as
+    appropriate and set the 'Level' column for those features to equal
+    the 'Level' for their parent features for consistency.  Note that
+    none of the features in the OpenAFS for Windows MSI package are
+    designed to be installed to run from 'source' or 'advertised'.  It
+    is recommended that you set 'msidbFeatureAttributesFavorLocal' (0),
+    'msidbFeatureAttributesFollowParent' (2) and
+    'msidbFeatureAttributesDisallowAdvertise' (8) attributes for new
+    features.
+
+    If you are creating new components, retain the same component GUID
+    when creating new transforms against new releases of the OpenAFS
+    MSI package.
+
     After making the adjustments to the MSI database using ORCA.EXE
     you can generate a transform with MSITRAN.EXE as follows :
 
diff --git a/doc/txt/winnotes/performance.txt b/doc/txt/winnotes/performance.txt
new file mode 100644 (file)
index 0000000..be370b6
--- /dev/null
@@ -0,0 +1,64 @@
+argos.mit.edu with 1.3.73 client
+171,194,368 byte file.  "fs flush" before each command
+
+200mb cache; No MaxMTU
+       write/crypt 2.793 MB/sec
+       read/crypt  2.897 MB/sec
+
+       write/clear 7.123 MB/sec
+       read/clear  5.991 MB/sec
+
+1.2.10(skyrope)
+        write/crypt:  1.836 MB/sec
+        read/crypt:   1.497 MB/sec
+
+        write/clear:  2.927 MB/sec
+        read/clear:   2.065 MB/sec
+
+
+                 1.2.10          1.3.73       improvement
+              ------------    ------------    -----------
+write/crypt   1.836 MB/sec    2.793 MB/sec       52.1%
+read/crypt    1.497 MB/sec    2.897 MB/sec       93.5%
+                              
+write/clear   2.927 MB/sec    7.123 MB/sec      143.4%
+read/clear    2.065 MB/sec    5.991 MB/sec      190.1%
+
+
+
+mitz@ANDREW.CMU.EDU tested the 1.3.73 client on his machine
+against his cell copying a 367181824 byte file.  "fs flush"
+was run prior to each command.
+
+
+Default MaxMTU; Default cache
+       write/crypt:  4.158 MB/sec
+       read/crypt:   5.730 MB/sec
+
+       write/clear:  4.537 MB/sec
+       read/clear:  16.762 MB/sec
+
+Changing the cache size made no difference
+
+No MaxMTU; 400MB cache
+       write/crypt:  4.863 MB/sec
+       read/crypt:   6.083 MB/sec
+
+       write/clear: 14.286 MB/sec
+       read/clear:  16.257 MB/sec
+
+From Andrew Linux with 1.2.10 on the same machine:
+       write/crypt:  5.358 MB/sec
+       read/crypt:  12.855 MB/sec
+
+       write/crypt  18.040 MB/sec (unique file names)
+       read/crypt   23.160 MB/sec (unique file names)
+
+       write/clear: 16.401 MB/sec
+       read/clear:  25.192 MB/sec
+
+
+        
+
+
+
index f7cab8d..0baa5ff 100644 (file)
@@ -29,14 +29,14 @@ Variable: LANadapter
 
 Value   : CacheSize
 Type    : DWORD
-Default : 20480 (CM_CONFIGDEFAULT_CACHESIZE)
+Default : 98304 (CM_CONFIGDEFAULT_CACHESIZE)
 Variable: cm_initParams.cacheSize
 
   Size of the AFS cache in 1k blocks.
 
 Value   : ChunkSize
 Type    : DWORD
-Default : 15 (CM_CONFIGDEFAULT_CHUNKSIZE)
+Default : 17 (CM_CONFIGDEFAULT_CHUNKSIZE)
 Variable: cm_logChunkSize (cm_chunkSize = 1 << cm_logChunkSize)
 
   Size of chunk for reading and writing. Actual chunk size is 2^cm_logChunkSize.
@@ -51,7 +51,7 @@ Variable: numBkgD
 
 Value  : ServerThreads
 Type   : DWORD
-Default        : 4 (CM_CONFIGDEFAULT_SVTHREADS)
+Default        : 25 (CM_CONFIGDEFAULT_SVTHREADS)
 Variable: numSvThreads
 
   Number of SMB server threads (number of threads of smb_Server). (see
@@ -59,7 +59,7 @@ Variable: numSvThreads
 
 Value  : Stats
 Type   : DWORD
-Default : 1000 (CM_CONFIGDEFAULT_STATS)
+Default : 10000 (CM_CONFIGDEFAULT_STATS)
 Variable: cm_initParams.nStatCaches
 
   Cache configuration.
@@ -103,13 +103,15 @@ Variable: cm_mountRoot
   be relative and suffixed to the reference directory (i.e. directory
   where the symlink exists)
  
+
 Value  : CachePath
 Type   : REG_SZ or REG_EXPAND_SZ
-Default : "%SYSTEMDRIVE%\AFSCache"
+Default : "%TEMP%\AFSCache"
 Variable: cm_CachePath
 
-  Location of on-disk cache file.  The default implies the root 
-  directory of the boot disk
+  Location of on-disk cache file.  The default is the SYSTEM account's
+  TEMP directory.  The attributes assigned to the file are HIDDEN and
+  SYSTEM.
 
 
 Value   : NonPersistentCaching
@@ -124,6 +126,18 @@ Variable: buf_CacheType
   using the "fs setcachesize" command.
 
 
+Value   : ValidateCache
+Type    : DWORD [0..2]
+Default : 1
+Variable: buf_CacheType
+
+  This value determines if and when persistent cache validation is 
+  performed.
+    0 - Validation is disabled
+    1 - Validation is performed at startup
+    2 - Validation is performed at shutdown
+
+
 Value  : TrapOnPanic
 Type   : DWORD {1,0}
 Default : 0
@@ -353,9 +367,154 @@ Type    : SZ
     to the provided drive letter.
 
 
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client]
+
+Value   : CellServDBDir
+Type   : REG_SZ
+Default : <not defined>
+
+  Specifies the directory containing the CellServDB file.
+  When this value is not specified, the AFS Client install
+  directory is used.
+
+
+Value   : VerifyServiceSignature
+Type   : REG_DWORD
+Default : 0x1
+
+  This value can be used to disable the runtime verification of 
+  the digital signatures applied to afsd_service.exe and the 
+  OpenAFS DLLs it loads.  This test is performed to verify that 
+  the DLLs which are loaded by afsd_service.exe are from the 
+  same distribution as afsd_service.exe.  This is to prevent
+  random errors caused when DLLs from one distribution of AFS
+  are loaded by another one.  This is not a security test.  The
+  reason for disabling this test is to free up additional memory
+  which can be used for a large cache size.
+
+
+Value   : IoctlDebug
+Type   : REG_DWORD
+Default : 0x0
+
+  This value can be used to debug the cause of pioctl() failures.
+  Set a non-zero value and the pioctl() library will output status
+  information to stdout.  Executing command line tools such as
+  tokens.exe, fs.exe, etc can then be used to determine why the
+  pioctl() call is failing. 
+
+
+Value   : StoreAnsiFilenames
+Type    : REG_DWORD
+Default : 0x0
+
+  This value can be used to force the AFS Client Service to
+  store filenames using the Windows system's ANSI character set
+  instead of the OEM Code Page character set which has traditionally
+  been used by SMB file systems.  
+
+  Note: The use of ANSI characters will render access to files
+  with 8-bit OEM file names unaccessible from Windows.  This option
+  is of use primarily when you wish to allow file names produced
+  on Windows to be accessible from Latin-1 Unix systems and vice
+  versa.
+
 
 Regkey:
-[HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider]
+[HKLM\SOFTWARE\OpenAFS\Client\CSCPolicy]
+
+Value   : "smb/cifs share name"
+Type    : REG_SZ
+Default : <none>
+
+    This key is used to map SMB/CIFS shares to Client Side Caching 
+    (off-line access) policies. For each share one of the following
+    policies may be used: "manual", "programs", "documents", "disable"
+
+    These values used to be stored in afsdsbmt.ini
+
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client\Freelance]
+
+Value   : "numeric value"
+Type    : REG_SZ
+Default : <none>
+
+    This key is used to store dot terminated mount point strings 
+    for use in constructing the fake root.afs volume when Freelance
+    (dynamic roots) mode is activated.
+
+        "athena.mit.edu#athena.mit.edu:root.cell."
+        ".athena.mit.edu%athena.mit.edu:root.cell."
+
+    These values used to be stored in afs_freelance.ini
+
+
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client\Freelance\Symlinks]
+
+Value   : "numeric value"
+Type    : REG_SZ
+Default : <none>
+
+    This key is used to store a dot terminated symlink strings 
+    for use in constructing the fake root.afs volume when Freelance
+    (dynamic roots) mode is activated.
+
+        "linkname:destination-path."
+        "athena:athena.mit.edu."
+        "home:athena.mit.edu\user\j\a\jaltman."
+        "filename:path\file."
+
+
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client\Submounts]
+
+Value   : "submount name"
+Type    : REG_EXPAND_SZ
+Default : <none>
+
+    This key is used to store mappings of unix style AFS paths
+    to submount names which can be referenced as UNC paths.
+    For example the submount string "/athena.mit.edu/user/j/a/jaltman"
+    can be associated with the submount name "jaltman.home".
+    This can then be referenced as the UNC path \\AFS\jaltman.home.
+
+    These values used to be stored in afsdsbmt.ini
+
+    NOTE: Submounts should no longer be used with OpenAFS.
+    Use the Windows Explorer to create drive mappings to AFS UNC
+    paths instead of using the AFS Submount mechanism.
+
+
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client\Server Preferences\VLDB]
+
+Value   : "hostname or ip address"
+Type    : REG_DWORD
+Default : <none>
+
+    This key is used to specify a default set of VLDB server preferences.
+    For each entry the value name will be either the IP address of a server
+    or a fully qualified domain name.  The value will be the ranking.  The
+    ranking will be adjusted by a random value between 0 and 256 prior to
+    the preference being set.
+
+
+Regkey:
+[HKLM\SOFTWARE\OpenAFS\Client\Server Preferences\File]
+
+Value   : "hostname or ip address"
+Type    : REG_DWORD
+Default : <none>
+
+    This key is used to specify a default set of File server preferences.
+    For each entry the value name will be either the IP address of a server
+    or a fully qualified domain name.  The value will be the ranking.  The
+    ranking will be adjusted by a random value between 0 and 256 prior to
+    the preference being set.
+
 
 
 2. Network provider parameters
@@ -422,61 +581,6 @@ NSIS    : %WINDIR%\SYSTEM32\afslogon.dll
   Specifies the DLL to use for the network provider
 
 
-Regkey:
-[HKLM\SOFTWARE\OpenAFS\Client]
-
-Value   : CellServDBDir
-Type   : REG_SZ
-Default : <not defined>
-
-  Specifies the directory containing the CellServDB file.
-  When this value is not specified, the AFS Client install
-  directory is used.
-
-
-Value   : VerifyServiceSignature
-Type   : REG_DWORD
-Default : 0x1
-
-  This value can be used to disable the runtime verification of 
-  the digital signatures applied to afsd_service.exe and the 
-  OpenAFS DLLs it loads.  This test is performed to verify that 
-  the DLLs which are loaded by afsd_service.exe are from the 
-  same distribution as afsd_service.exe.  This is to prevent
-  random errors caused when DLLs from one distribution of AFS
-  are loaded by another one.  This is not a security test.  The
-  reason for disabling this test is to free up additional memory
-  which can be used for a large cache size.
-
-
-Value   : IoctlDebug
-Type   : REG_DWORD
-Default : 0x0
-
-  This value can be used to debug the cause of pioctl() failures.
-  Set a non-zero value and the pioctl() library will output status
-  information to stdout.  Executing command line tools such as
-  tokens.exe, fs.exe, etc can then be used to determine why the
-  pioctl() call is failing. 
-
-
-Value   : StoreAnsiFilenames
-Type    : REG_DWORD
-Default : 0x0
-
-  This value can be used to force the AFS Client Service to
-  store filenames using the Windows system's ANSI character set
-  instead of the OEM Code Page character set which has traditionally
-  been used by SMB file systems.  
-
-  Note: The use of ANSI characters will render access to files
-  with 8-bit OEM file names unaccessible from Windows.  This option
-  is of use primarily when you wish to allow file names produced
-  on Windows to be accessible from Latin-1 Unix systems and vice
-  versa.
-
-
-
 2.1 Domain specific configuration keys for the Network Provider
 ---------------------------------------------------------------
 
@@ -574,6 +678,14 @@ in 2.1.1.  The effective values are chosen as described in 2.1.2.
 
      See description of LoginRetryInterval.
 
+  Value   : TheseCells
+  Type    : REG_MULTI_SZ
+  NSIS    : <not set>
+
+    When Kerberos 5 is being used, TheseCells provides a list of additional
+    cells for which tokens should be obtained with the default Kerberos 5 
+    principal.
+
 
 2.1.2  Selection of effective values for domain specific configuration
 ----------------------------------------------------------------------
@@ -755,69 +867,6 @@ Default : <none>
   These values used to be stored in the afsdsbmt.ini file.
 
 
-Regkey:
-[HKLM\SOFTWARE\OpenAFS\Client\CSCPolicy]
-
-Value   : "smb/cifs share name"
-Type    : REG_SZ
-Default : <none>
-
-    This key is used to map SMB/CIFS shares to Client Side Caching 
-    (off-line access) policies. For each share one of the following
-    policies may be used: "manual", "programs", "documents", "disable"
-
-    These values used to be stored in afsdsbmt.ini
-
-Regkey:
-[HKLM\SOFTWARE\OpenAFS\Client\Freelance]
-
-Value   : "numeric value"
-Type    : REG_SZ
-Default : <none>
-
-    This key is used to store dot terminated mount point strings 
-    for use in constructing the fake root.afs volume when Freelance
-    (dynamic roots) mode is activated.
-
-        "athena.mit.edu#athena.mit.edu:root.cell."
-        ".athena.mit.edu%athena.mit.edu:root.cell."
-
-    These values used to be stored in afs_freelance.ini
-
-
-Regkey:
-[HKLM\SOFTWARE\OpenAFS\Client\Freelance\Symlinks]
-
-Value   : "numeric value"
-Type    : REG_SZ
-Default : <none>
-
-    This key is used to store a dot terminated symlink strings 
-    for use in constructing the fake root.afs volume when Freelance
-    (dynamic roots) mode is activated.
-
-        "linkname:destination-path."
-        "athena:athena.mit.edu."
-        "home:athena.mit.edu\user\j\a\jaltman."
-        "filename:path\file."
-
-
-Regkey:
-[HKLM\SOFTWARE\OpenAFS\Client\Submounts]
-
-Value   : "submount name"
-Type    : REG_EXPAND_SZ
-Default : <none>
-
-    This key is used to store mappings of unix style AFS paths
-    to submount names which can be referenced as UNC paths.
-    For example the submount string "/athena.mit.edu/user/j/a/jaltman"
-    can be associated with the submount name "jaltman.home".
-    This can then be referenced as the UNC path \\AFS\jaltman.home.
-
-    These values used to be stored in afsdsbmt.ini
-
-
 ENVIRONMENT VARIABLES:
 
 Variable: AFS_RPC_ENCRYPT 
diff --git a/src/WINNT/afsadmsvr/.cvsignore b/src/WINNT/afsadmsvr/.cvsignore
new file mode 100644 (file)
index 0000000..af83500
--- /dev/null
@@ -0,0 +1,5 @@
+iTaAfsAdmSvr.h
+iTaAfsAdmSvrTypes.h
+iTaAfsAdmSvr_c.c
+iTaAfsAdmSvr_s.c
+
diff --git a/src/WINNT/afsapplib/.cvsignore b/src/WINNT/afsapplib/.cvsignore
new file mode 100644 (file)
index 0000000..45415bd
--- /dev/null
@@ -0,0 +1,2 @@
+AFS_component_version_number.h
+lang/AFS_component_version_number.h
index d4976d0..df0fe9d 100644 (file)
@@ -127,6 +127,7 @@ $(DLLFILE) : $(DLLOBJS) $(DLLLIBS)
 
 clean::
        $(CD) lang
+        @if exist AFS_component_version_number.h del AFS_component_version_number.h
        for /f %l in ('dir /B ??_??') do ( if exist @$(NTLANG) do @$(NTLANG) %l $(MAKECMD) /nologo /f NTMakefile clean )
        $(CD) ..
 
index c3be71c..cbdb89a 100644 (file)
@@ -62,10 +62,11 @@ INCFILES =\
        $(INCFILEDIR)\cm_dnlc.h \
        $(INCFILEDIR)\cm_buf.h \
        $(INCFILEDIR)\cm_freelance.h \
-    $(INCFILEDIR)\afsd_eventlog.h \
-    $(INCFILEDIR)\afsd_eventmessages.h \
-    $(INCFILEDIR)\afskfw.h \
-    $(INCFILEDIR)\afsicf.h
+        $(INCFILEDIR)\cm_memmap.h \
+        $(INCFILEDIR)\afsd_eventlog.h \
+        $(INCFILEDIR)\afsd_eventmessages.h \
+        $(INCFILEDIR)\afskfw.h \
+        $(INCFILEDIR)\afsicf.h
 
 IDLFILES =\
        afsrpc.h $(OUT)\afsrpc_c.obj
@@ -111,14 +112,15 @@ AFSDOBJS=\
        $(OUT)\cm_aclent.obj \
        $(OUT)\cm_dnlc.obj \
        $(OUT)\cm_rpc.obj \
+        $(OUT)\cm_memmap.obj \
        $(OUT)\afsrpc_s.obj \
 !IFDEF OSICRASH
        $(OUT)\afsdcrash.obj \
 !ENDIF
-    $(OUT)\cm_freelance.obj \
-    $(OUT)\afsd_eventlog.obj \
-    $(OUT)\afsd_flushvol.obj \
-    $(OUT)\afsicf.obj
+        $(OUT)\cm_freelance.obj \
+        $(OUT)\afsd_eventlog.obj \
+        $(OUT)\afsd_flushvol.obj \
+        $(OUT)\afsicf.obj
 
 $(AFSDOBJS):
 
@@ -127,6 +129,8 @@ $(OUT)\cm_conn.obj: cm_conn.c
 
 FSOBJS=$(OUT)\fs.obj $(OUT)\fs_utils.obj
 
+CMDBGOBJS=$(OUT)\cmdebug.obj
+
 SLOBJS=$(OUT)\symlink.obj $(OUT)\fs_utils.obj
 
 ILIBDIR = $(DESTDIR)\lib
@@ -272,10 +276,12 @@ install: install_headers install_objs $(CONF_DLLFILE) \
        $(EXEDIR)\klog.exe \
        $(EXEDIR)\tokens.exe \
        $(EXEDIR)\unlog.exe $(EXEDIR)\afsd.exe $(EXEDIR)\afsd_service.exe \
-       $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \
+       $(EXEDIR)\fs.exe \
+        $(EXEDIR)\symlink.exe \
+        $(EXEDIR)\afsdacl.exe \
        $(LOGON_DLLFILE) \
        $(EXEDIR)\afsshare.exe \
-       $(DESTDIR)\bin\kpasswd.exe
+       $(DESTDIR)\bin\kpasswd.exe $(EXEDIR)\cmdebug.exe
 
 install9X: install_headers $(CONF_DLLFILE) \
        $(EXEDIR)\klog.exe \
@@ -292,7 +298,7 @@ install_libutils: install_headers $(CONF_DLLFILE) \
        $(EXEDIR)\unlog.exe \
        $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \
        $(EXEDIR)\afsshare.exe \
-       $(DESTDIR)\bin\kpasswd.exe
+       $(DESTDIR)\bin\kpasswd.exe $(EXEDIR)\cmdebug.exe
 
 ############################################################################
 # Local clean target; augments predefined clean target
@@ -318,19 +324,33 @@ EXELIBS = \
        $(DESTDIR)\lib\libosi.lib \
        $(DESTDIR)\lib\libafsconf.lib
 
+EXELIBS2 = \
+        $(DESTDIR)\lib\afsrpc.lib \
+       $(DESTDIR)\lib\afs\afsprot.lib \
+       $(DESTDIR)\lib\afs\afspioctl.lib \
+       $(DESTDIR)\lib\afs\afscom_err.lib \
+       $(DESTDIR)\lib\afs\afscmd.lib \
+       $(DESTDIR)\lib\afs\afsutil.lib \
+       $(DESTDIR)\lib\afsubik.lib \
+       $(DESTDIR)\lib\afsrxkad.lib \
+       $(DESTDIR)\lib\afsdes.lib \
+       $(DESTDIR)\lib\afslwp.lib \
+       $(DESTDIR)\lib\libosi.lib \
+       $(DESTDIR)\lib\libafsconf.lib
+
 # klog.exe
 $(EXEDIR)\klog.exe: $(OUT)\cklog.obj $(OUT)\klog.res $(EXELIBS)
-       $(EXECONLINK) dnsapi.lib mpr.lib
+       $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib
        $(EXEPREP)
 
 # tokens.exe
 $(EXEDIR)\tokens.exe: $(OUT)\ctokens.obj $(OUT)\tokens.res $(EXELIBS)
-       $(EXECONLINK) dnsapi.lib mpr.lib
+       $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib
        $(EXEPREP)
 
 # unlog.exe
 $(EXEDIR)\unlog.exe: $(OUT)\cunlog.obj $(OUT)\unlog.res $(EXELIBS)
-       $(EXECONLINK) dnsapi.lib mpr.lib
+       $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib
        $(EXEPREP)
 
 # afsd.exe
@@ -347,7 +367,8 @@ AFSD_SDKLIBS =\
         mpr.lib \
         secur32.lib \
         ole32.lib \
-        oleaut32.lib
+        oleaut32.lib \
+        iphlpapi.lib
 
 AFSD_EXELIBS =\
        $(DESTDIR)\lib\libosi.lib \
@@ -371,12 +392,17 @@ $(EXEDIR)\afsd_service.exe: $(OUT)\afsd_service.obj $(AFSDOBJS) $(OUT)\afsd_serv
 
 # fs.exe
 $(EXEDIR)\fs.exe: $(FSOBJS) $(OUT)\fs.res $(EXELIBS)
-       $(EXECONLINK) dnsapi.lib mpr.lib
+       $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib
+       $(EXEPREP)
+
+# cmdebug.exe
+$(EXEDIR)\cmdebug.exe: $(CMDBGOBJS) $(OUT)\cmdebug.res $(EXELIBS2)
+       $(EXECONLINK) $(EXELIBS2) dnsapi.lib mpr.lib iphlpapi.lib rpcrt4.lib
        $(EXEPREP)
 
 # symlink.exe
 $(EXEDIR)\symlink.exe: $(SLOBJS) $(OUT)\symlink.res  $(EXELIBS)
-       $(EXECONLINK) dnsapi.lib mpr.lib
+       $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib
        $(EXEPREP)
 
 # afsshare.exe
@@ -384,6 +410,11 @@ $(EXEDIR)\afsshare.exe: $(OUT)\afsshare.obj $(OUT)\afsshare.res
        $(EXECONLINK)
        $(EXEPREP)
 
+# afsdacl.exe
+$(EXEDIR)\afsdacl.exe: $(OUT)\afsdacl.obj $(OUT)\afsdacl.res
+       $(EXECONLINK)
+       $(EXEPREP)
+
 # kpasswd.exe - built in kauth, but rebuild here to make pthread-based,
 #    which is required for Windows 95.  At some point it would be nice
 #    for all commands to be pthread based, in which case they should
@@ -402,7 +433,7 @@ KPASSWD_OBJS =\
 KPASSWD_LIBS =\
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\afsrpc.lib \
-    $(DESTDIR)\lib\afsrx.lib \
+        $(DESTDIR)\lib\afsrx.lib \
        $(DESTDIR)\lib\afs\afscmd.lib \
        $(DESTDIR)\lib\afsdes.lib \
        $(DESTDIR)\lib\afs\afsutil.lib
@@ -455,7 +486,7 @@ clean::
        $(DEL) $(OUT)\*.res
        $(DEL) afsrpc.h
        $(DEL) afsrpc_?.*
-    $(DEL) afsd_eventmessages.h
+        $(DEL) afsd_eventmessages.h
        $(DEL) $(CONF_DLLFILE)
        $(DEL) $(LOGON_DLLFILE)
        $(DEL) $(LOG95_DLLFILE)
index 495e2ba..749aac5 100644 (file)
@@ -39,6 +39,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include <afs/prs_fs.h>
 
 #include <osi.h>
+#include "cm_config.h"
 #include "cm_user.h"
 #include "cm_callback.h"
 #ifdef DISKCACHE95
@@ -47,19 +48,19 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include "cm_conn.h"
 #include "cm_aclent.h"
 #include "cm_cell.h"
-#include "cm_config.h"
 #include "cm_server.h"
-#include "cm_volume.h"
 #include "cm_scache.h"
+#include "cm_volume.h"
 #include "cm_dcache.h"
 #include "cm_access.h"
+#include "cm_utils.h"
 #include "cm_vnodeops.h"
 #include "cm_dir.h"
-#include "cm_utils.h"
 #include "cm_daemon.h"
 #include "cm_ioctl.h"
 #include "cm_dnlc.h"
 #include "cm_buf.h"
+#include "cm_memmap.h"
 #include "cm_freelance.h"
 #include "smb_ioctl.h"
 #include "afsd_init.h"
@@ -100,29 +101,31 @@ extern BOOL isGateway;
 extern BOOL reportSessionStartups;
 
 #ifdef AFS_FREELANCE_CLIENT
+extern char *cm_FakeRootDir;                           // the fake root.afs directory
 
-// yj: Variables used by Freelance Client
-extern char *cm_FakeRootDir;                                           // the fake root.afs directory
-
-extern int cm_noLocalMountPoints;                                      // no. of fake mountpoints
+extern int cm_noLocalMountPoints;                      // no. of fake mountpoints
 
 extern cm_localMountPoint_t* cm_localMountPoints;      // array of fake mountpoints
 
-extern int cm_fakeDirSize;                                                     // size (in bytes) of fake root.afs directory
+extern int cm_fakeDirSize;                             // size (in bytes) of fake root.afs directory
 
-extern int cm_fakeDirCallback;                                         // state of the fake root.afs directory. indicates
+extern int cm_fakeDirCallback;                         // state of the fake root.afs directory. indicates
                                                                                                        // if it needs to be refreshed
 
-extern int cm_fakeGettingCallback;                                     // 1 if currently updating the fake root.afs directory,
+extern int cm_fakeGettingCallback;                     // 1 if currently updating the fake root.afs directory,
                                                                                                        // 0 otherwise
 
-extern int cm_fakeDirVersion;                                          // the version number of the root.afs directory. used 
-                                                                                                       // invalidate all the buffers containing root.afs data
-                                                                                                       // after reinitialization
-// ------------------------------------------
+extern int cm_fakeDirVersion;                          // the version number of the root.afs directory. used 
 #endif /* AFS_FREELANCE_CLIENT */
 
 extern int cm_dnsEnabled;
 extern int cm_freelanceEnabled;
 
+#define CAPABILITY_ERRORTRANS (1<<0)
+#define CAPABILITY_BITS 1
+
+#define DFS_SUPPORT 1
+#define LOG_PACKET 1
+#undef  NOTSERVICE
+
 #endif /* AFSD_H_ENV */
index 10ecffd..a9f60f1 100644 (file)
 #include <windows.h>
 #include <stdarg.h>
 #include <string.h>
+#include <WINNT/afsreg.h>
 #include "afsd_eventlog.h"
 
-#define SZSERVICEPATH          "System\\CurrentControlSet\\Services\\"
-#define SZSERVICENAME          "TransarcAFSDaemon"
-
-static CHAR    szKeyName[] = "System\\CurrentControlSet\\Services\\EventLog\\Application\\TransarcAFSDaemon";
+static CHAR    szKeyName[] = AFSREG_APPLOG_SUBKEY "\\" AFSREG_CLT_SVC_NAME;
 
 static BOOL    GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize);
 static BOOL    AddEventSource(void);
@@ -24,18 +22,13 @@ static BOOL
 GetServicePath(LPTSTR lpPathBuf, PDWORD pdwPathBufSize)
 {
        HKEY    hKey = NULL; 
-       UCHAR   szBuf[MAX_PATH]; 
        DWORD   dwData = 0;
        BOOL    bRet = TRUE;
 
        do {
-               // Prepare path in Registry
-               memset(szBuf, '\0', MAX_PATH);
-               strcpy(szBuf, SZSERVICEPATH);
-               strcat(szBuf, "TransarcAFSDaemon");
                
                // Open key
-               if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey ) )
+               if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_SVR_SVC_SUBKEY, 0, KEY_QUERY_VALUE, &hKey ) )
                {               
                        bRet = FALSE;
                        break;
@@ -103,7 +96,7 @@ AddEventSource()
                        // Add the name to the EventMessageFile subkey. 
                        if ( RegSetValueEx(
                                        hKey,                   // subkey handle 
-                                       "EventMessageFile",     // value name 
+                                       AFSREG_SVR_APPLOG_MSGFILE_VALUE,        // value name 
                                        0,                      // must be zero 
                                        REG_EXPAND_SZ,          // value type 
                                        (LPBYTE) szBuf,         // pointer to value data 
@@ -119,7 +112,7 @@ AddEventSource()
  
                        if ( RegSetValueEx(
                                        hKey,                   // subkey handle 
-                                       "TypesSupported",       // value name 
+                                       AFSREG_SVR_APPLOG_MSGTYPE_VALUE,        // value name 
                                        0,                      // must be zero 
                                        REG_DWORD,              // value type 
                                        (LPBYTE) &dwData,       // pointer to value data 
@@ -137,7 +130,7 @@ AddEventSource()
                        dwData = MAX_PATH;
                        if ( RegQueryValueEx( 
                                        hKey,                   // handle to key
-                                       "EventMessageFile",     // value name
+                                       AFSREG_SVR_APPLOG_MSGFILE_VALUE,        // value name
                                        NULL,                   // reserved
                                        NULL,                   // type buffer
                                        (LPBYTE) szBuf,         // data buffer
@@ -187,7 +180,7 @@ LogEvent(WORD wEventType, DWORD dwEventID, LPTSTR lpString, ...)
                return;
 
        // Get a handle to the event log.
-       hEventSource = RegisterEventSource(NULL, SZSERVICENAME);
+       hEventSource = RegisterEventSource(NULL, AFSREG_CLT_SVC_PARAM_KEY);
        if (hEventSource == NULL)
                return;
 
index e2ff15a..a3c9b34 100644 (file)
 #include <rx\rx.h>
 #include <rx\rx_null.h>
 #include <WINNT/syscfg.h>
+#include <WINNT/afsreg.h>
 
 #include "smb.h"
 #include "cm_rpc.h"
 #include "lanahelper.h"
 #include <strsafe.h>
 #include "afsicf.h"
+#include "cm_memmap.h"
 
 extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
 extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
 
 extern afs_int32 cryptall;
 
-char AFSConfigKeyName[] =
-       "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
-char OpenAFSConfigKeyName[] =
-       "SOFTWARE\\OpenAFS\\Client";
-
 osi_log_t *afsd_logp;
 
-char cm_rootVolumeName[64];
+cm_config_data_t        cm_data;
+
+char cm_rootVolumeName[VL_MAXNAMELEN];
 DWORD cm_rootVolumeNameLen;
-cm_volume_t *cm_rootVolumep = NULL;
-cm_cell_t *cm_rootCellp = NULL;
-cm_fid_t cm_rootFid;
-cm_scache_t *cm_rootSCachep = NULL;
 char cm_mountRoot[1024];
 DWORD cm_mountRootLen;
 int cm_logChunkSize;
@@ -58,7 +53,7 @@ int cm_chunkSize;
 char *cm_FakeRootDir;
 #endif /* freelance */
 
-int smb_UseV3;
+int smb_UseV3 = 1;
 
 int LANadapter;
 
@@ -76,6 +71,7 @@ char cm_NetbiosName[MAX_NB_NAME_LENGTH] = "";
 
 char cm_CachePath[MAX_PATH];
 DWORD cm_CachePathLen;
+DWORD cm_ValidateCache = 1;
 
 BOOL isGateway = FALSE;
 
@@ -164,7 +160,7 @@ afsi_start()
     afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                            OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
 
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         dummyLen = sizeof(maxLogSize);
@@ -314,15 +310,15 @@ configureBackConnectionHostNames(void)
                                &hkLsa) == ERROR_SUCCESS )
             {
                 dwSize = sizeof(DWORD);
-                if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, &dwValue, &dwSize) != ERROR_SUCCESS ||
+                if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS ||
                      dwValue == 0 ) {
                     dwType = REG_DWORD;
                     dwSize = sizeof(DWORD);
                     dwValue = 1;
-                    RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, &dwValue, dwSize);
+                    RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
 
                     if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
-                                        "SOFTWARE\\OpenAFS\\Client",
+                                        AFSREG_CLT_OPENAFS_SUBKEY,
                                         0,
                                         NULL,
                                         REG_OPTION_NON_VOLATILE,
@@ -334,7 +330,7 @@ configureBackConnectionHostNames(void)
                         dwType = REG_DWORD;
                         dwSize = sizeof(DWORD);
                         dwValue = 1;
-                        RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, &dwValue, dwSize);
+                        RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
                         RegCloseKey(hkClient);
                     }
                     RegCloseKey(hkLsa);
@@ -342,7 +338,7 @@ configureBackConnectionHostNames(void)
             }
         } else {
             if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
-                                "SOFTWARE\\OpenAFS\\Client",
+                                AFSREG_CLT_OPENAFS_SUBKEY,
                                 0,
                                 NULL,
                                 REG_OPTION_NON_VOLATILE,
@@ -352,7 +348,7 @@ configureBackConnectionHostNames(void)
                                 NULL) == ERROR_SUCCESS) {
 
                 dwSize = sizeof(DWORD);
-                if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, &dwValue, &dwSize) == ERROR_SUCCESS &&
+                if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS &&
                      dwValue == 1 ) {
                     if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
                                        "SYSTEM\\CurrentControlSet\\Control\\Lsa",
@@ -372,6 +368,157 @@ configureBackConnectionHostNames(void)
     }
 }
 
+#if !defined(DJGPP)
+static void afsd_InitServerPreferences(void)
+{
+    HKEY hkPrefs = 0;
+    DWORD dwType, dwSize;
+    DWORD dwPrefs = 0;
+    DWORD dwIndex;
+    TCHAR szHost[256];
+    DWORD dwHostSize = 256;
+    DWORD dwRank;
+    struct sockaddr_in saddr;
+    cm_server_t       *tsp;
+
+    if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                      AFSREG_CLT_OPENAFS_SUBKEY "\\Server Preferences\\VLDB",
+                      0,
+                      KEY_READ|KEY_QUERY_VALUE,
+                      &hkPrefs) == ERROR_SUCCESS) {
+
+        RegQueryInfoKey( hkPrefs,
+                         NULL,  /* lpClass */
+                         NULL,  /* lpcClass */
+                         NULL,  /* lpReserved */
+                         NULL,  /* lpcSubKeys */
+                         NULL,  /* lpcMaxSubKeyLen */
+                         NULL,  /* lpcMaxClassLen */
+                         &dwPrefs, /* lpcValues */
+                         NULL,  /* lpcMaxValueNameLen */
+                         NULL,  /* lpcMaxValueLen */
+                         NULL,  /* lpcbSecurityDescriptor */
+                         NULL   /* lpftLastWriteTime */
+                         );
+
+        for ( dwIndex = 0 ; dwIndex < dwPrefs; dwIndex++ ) {
+
+            dwSize = sizeof(DWORD);
+            dwHostSize = 256;
+
+            if (RegEnumValue( hkPrefs, dwIndex, szHost, &dwHostSize, NULL,
+                              &dwType, (LPBYTE)&dwRank, &dwSize))
+            {
+                afsi_log("RegEnumValue(hkPrefs) failed");
+                continue;
+            }
+
+            afsi_log("VLDB Server Preference: %s = %d",szHost, dwRank);
+
+            if (isdigit(szHost[0]))
+            {
+                if ((saddr.sin_addr.S_un.S_addr = inet_addr (szHost)) == INADDR_NONE)
+                    continue;
+            } else {
+                HOSTENT *pEntry;
+                if ((pEntry = gethostbyname (szHost)) == NULL)
+                    continue;
+
+                saddr.sin_addr.S_un.S_addr = *(unsigned long *)pEntry->h_addr;
+            }
+            saddr.sin_family = AF_INET;
+            dwRank += (rand() & 0x000f);
+
+            tsp = cm_FindServer(&saddr, CM_SERVER_VLDB);
+            if ( tsp )         /* an existing server - ref count increased */
+            {
+                tsp->ipRank = (USHORT)dwRank; /* no need to protect by mutex*/
+
+                /* set preferences for an existing vlserver */
+                cm_ChangeRankCellVLServer(tsp);
+                cm_PutServer(tsp);  /* decrease refcount */
+            }
+            else       /* add a new server without a cell */
+            {
+                tsp = cm_NewServer(&saddr, CM_SERVER_VLDB, NULL); /* refcount = 1 */
+                tsp->ipRank = (USHORT)dwRank;
+            }
+        }
+
+        RegCloseKey(hkPrefs);
+    }
+
+    if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                      AFSREG_CLT_OPENAFS_SUBKEY "\\Server Preferences\\File",
+                      0,
+                      KEY_READ|KEY_QUERY_VALUE,
+                      &hkPrefs) == ERROR_SUCCESS) {
+
+        RegQueryInfoKey( hkPrefs,
+                         NULL,  /* lpClass */
+                         NULL,  /* lpcClass */
+                         NULL,  /* lpReserved */
+                         NULL,  /* lpcSubKeys */
+                         NULL,  /* lpcMaxSubKeyLen */
+                         NULL,  /* lpcMaxClassLen */
+                         &dwPrefs, /* lpcValues */
+                         NULL,  /* lpcMaxValueNameLen */
+                         NULL,  /* lpcMaxValueLen */
+                         NULL,  /* lpcbSecurityDescriptor */
+                         NULL   /* lpftLastWriteTime */
+                         );
+
+        for ( dwIndex = 0 ; dwIndex < dwPrefs; dwIndex++ ) {
+
+            dwSize = sizeof(DWORD);
+            dwHostSize = 256;
+
+            if (RegEnumValue( hkPrefs, dwIndex, szHost, &dwHostSize, NULL,
+                              &dwType, (LPBYTE)&dwRank, &dwSize))
+            {
+                afsi_log("RegEnumValue(hkPrefs) failed");
+                continue;
+            }
+
+            afsi_log("File Server Preference: %s = %d",szHost, dwRank);
+
+            if (isdigit(szHost[0]))
+            {
+                if ((saddr.sin_addr.S_un.S_addr = inet_addr (szHost)) == INADDR_NONE)
+                    continue;
+            } else {
+                HOSTENT *pEntry;
+                if ((pEntry = gethostbyname (szHost)) == NULL)
+                    continue;
+
+                saddr.sin_addr.S_un.S_addr = *(unsigned long *)pEntry->h_addr;
+            }
+            saddr.sin_family = AF_INET;
+            dwRank += (rand() & 0x000f);
+
+            tsp = cm_FindServer(&saddr, CM_SERVER_FILE);
+            if ( tsp )         /* an existing server - ref count increased */
+            {
+                tsp->ipRank = (USHORT)dwRank; /* no need to protect by mutex*/
+
+                /* find volumes which might have RO copy 
+                /* on server and change the ordering of 
+                 * their RO list 
+                 */
+                cm_ChangeRankVolume(tsp);
+                cm_PutServer(tsp);  /* decrease refcount */
+            }
+            else       /* add a new server without a cell */
+            {
+                tsp = cm_NewServer(&saddr, CM_SERVER_FILE, NULL); /* refcount = 1 */
+                tsp->ipRank = (USHORT)dwRank;
+            }
+        }
+
+        RegCloseKey(hkPrefs);
+    }
+}
+#endif /* DJGPP */
 
 /*
  * AFSD Initialization
@@ -380,10 +527,10 @@ configureBackConnectionHostNames(void)
 int afsd_InitCM(char **reasonP)
 {
     osi_uid_t debugID;
-    long cacheBlocks;
-    long cacheSize;
+    DWORD cacheBlocks;
+    DWORD cacheSize;
     long logChunkSize;
-    long stats;
+    DWORD stats;
     long traceBufSize;
     long maxcpus;
     long ltt, ltto;
@@ -394,7 +541,7 @@ int afsd_InitCM(char **reasonP)
     static struct rx_securityClass *nullServerSecurityClassp;
     struct hostent *thp;
     char *msgBuf;
-    char buf[1024], *p, *q;
+    char buf[1024];
     HKEY parmKey;
     DWORD dummyLen;
     DWORD regType;
@@ -403,6 +550,12 @@ int afsd_InitCM(char **reasonP)
     WSADATA WSAjunk;
     lana_number_t lanaNum;
     int i;
+    char *p, *q; 
+    int cm_noIPAddr;         /* number of client network interfaces */
+    int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
+    int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
+    int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
+    int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
 
     WSAStartup(0x0101, &WSAjunk);
 
@@ -429,7 +582,7 @@ int afsd_InitCM(char **reasonP)
     srand(ntohl(cm_HostAddr));
 
     /* Look up configuration parameters in Registry */
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code != ERROR_SUCCESS) {
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
@@ -613,7 +766,7 @@ int afsd_InitCM(char **reasonP)
     if (code == ERROR_SUCCESS && buf[0]) {
         if (regType == REG_EXPAND_SZ) {
             dummyLen = ExpandEnvironmentStrings(buf, cm_CachePath, sizeof(cm_CachePath));
-            if(dummyLen > sizeof(cm_CachePath)) {
+            if (dummyLen > sizeof(cm_CachePath)) {
                 afsi_log("Cache path [%s] longer than %d after expanding env strings", buf, sizeof(cm_CachePath));
                 osi_panic("CachePath too long", __FILE__, __LINE__);
             }
@@ -633,13 +786,27 @@ int afsd_InitCM(char **reasonP)
 
     dummyLen = sizeof(virtualCache);
     code = RegQueryValueEx(parmKey, "NonPersistentCaching", NULL, NULL,
-                            &virtualCache, &dummyLen);
-    if (code == ERROR_SUCCESS && virtualCache) {
-        buf_cacheType = CM_BUF_CACHETYPE_VIRTUAL;
-    } else {
-        buf_cacheType = CM_BUF_CACHETYPE_FILE;
+                            (LPBYTE)&virtualCache, &dummyLen);
+    afsi_log("Cache type is %s", (virtualCache?"VIRTUAL":"FILE"));
+
+    if (!virtualCache) {
+        dummyLen = sizeof(cm_ValidateCache);
+        code = RegQueryValueEx(parmKey, "ValidateCache", NULL, NULL,
+                               (LPBYTE)&cm_ValidateCache, &dummyLen);
+        if ( cm_ValidateCache < 0 || cm_ValidateCache > 2 )
+            cm_ValidateCache = 1;
+        switch (cm_ValidateCache) {
+        case 0:
+            afsi_log("Cache Validation disabled");
+            break;
+        case 1:
+            afsi_log("Cache Validation on Startup");
+            break;
+        case 2:
+            afsi_log("Cache Validation on Startup and Shutdown");
+            break;
+        }
     }
-    afsi_log("Cache type is %s", ((buf_cacheType == CM_BUF_CACHETYPE_FILE)?"FILE":"VIRTUAL"));
 
     dummyLen = sizeof(traceOnPanic);
     code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
@@ -826,7 +993,7 @@ int afsd_InitCM(char **reasonP)
     RegCloseKey (parmKey);
 
     /* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
-    if(SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
+    if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
         LANadapter = (lanaNum == LANA_INVALID)? -1: lanaNum;
 
         if (LANadapter != -1)
@@ -844,13 +1011,7 @@ int afsd_InitCM(char **reasonP)
         osi_panic(buf, __FILE__, __LINE__);
     }
 
-    /* setup early variables */
-    /* These both used to be configurable. */
-    smb_UseV3 = 1;
-    buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
-
-    /* turn from 1024 byte units into memory blocks */
-    cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
+    cacheBlocks = (cacheSize * 1024) / CM_CONFIGDEFAULT_BLOCKSIZE;
         
     /* get network related info */
     cm_noIPAddr = CM_MAXINTERFACE_ADDR;
@@ -869,13 +1030,13 @@ int afsd_InitCM(char **reasonP)
      */
     cm_initParams.nChunkFiles = 0;
     cm_initParams.nStatCaches = stats;
-    cm_initParams.nDataCaches = 0;
-    cm_initParams.nVolumeCaches = 0;
+    cm_initParams.nDataCaches = cacheBlocks;
+    cm_initParams.nVolumeCaches = stats/2;
     cm_initParams.firstChunkSize = cm_chunkSize;
     cm_initParams.otherChunkSize = cm_chunkSize;
     cm_initParams.cacheSize = cacheSize;
     cm_initParams.setTime = 0;
-    cm_initParams.memCache = 0;
+    cm_initParams.memCache = 1;
 
     /* Set RX parameters before initializing RX */
     if ( rx_nojumbo ) {
@@ -897,28 +1058,20 @@ int afsd_InitCM(char **reasonP)
     /* init user daemon, and other packages */
     cm_InitUser();
 
-    cm_InitACLCache(2*stats);
-
     cm_InitConn();
 
-    cm_InitCell();
-        
     cm_InitServer();
         
-    cm_InitVolume();
-
     cm_InitIoctl();
         
     smb_InitIoctl();
         
     cm_InitCallback();
         
-    cm_InitSCache(stats);
-        
-    code = cm_InitDCache(0, cacheBlocks);
-    afsi_log("cm_InitDCache code %x", code);
+    code = cm_InitMappedMemory(virtualCache, cm_CachePath, stats, cm_chunkSize, cacheBlocks);
+    afsi_log("cm_InitMappedMemory code %x", code);
     if (code != 0) {
-        *reasonP = "error initializing cache";
+        *reasonP = "error initializing cache file";
         return -1;
     }
 
@@ -972,13 +1125,13 @@ int afsd_InitCM(char **reasonP)
         return -1;
     }   
     else if (cm_freelanceEnabled)
-        cm_rootCellp = NULL;
+        cm_data.rootCellp = NULL;
 
     if (code == 0 && !cm_freelanceEnabled) 
     {
-        cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
-        afsi_log("cm_GetCell addr %x", (int)cm_rootCellp);
-        if (cm_rootCellp == NULL) 
+        cm_data.rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
+        afsi_log("cm_GetCell addr %x", (int)cm_data.rootCellp);
+        if (cm_data.rootCellp == NULL) 
         {
             *reasonP = "can't find root cell in afsdcell.ini";
             return -1;
@@ -993,6 +1146,9 @@ int afsd_InitCM(char **reasonP)
     /* Initialize the RPC server for session keys */
     RpcInit();
 
+#if !defined(DJGPP)
+    afsd_InitServerPreferences();
+#endif
     return 0;
 }
 
@@ -1006,11 +1162,11 @@ int afsd_InitDaemons(char **reasonP)
     /* this should really be in an init daemon from here on down */
 
     if (!cm_freelanceEnabled) {
-               osi_Log0(afsd_logp, "Loading Root Volume from cell");
-        code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
-                                  &req, CM_FLAG_CREATE, &cm_rootVolumep);
+        osi_Log0(afsd_logp, "Loading Root Volume from cell");
+        code = cm_GetVolumeByName(cm_data.rootCellp, cm_rootVolumeName, cm_rootUserp,
+                                  &req, CM_FLAG_CREATE, &cm_data.rootVolumep);
         afsi_log("cm_GetVolumeByName code %x root vol %x", code,
-                 (code ? (cm_volume_t *)-1 : cm_rootVolumep));
+                 (code ? (cm_volume_t *)-1 : cm_data.rootVolumep));
         if (code != 0) {
             *reasonP = "can't find root volume in root cell";
             return -1;
@@ -1019,24 +1175,24 @@ int afsd_InitDaemons(char **reasonP)
 
     /* compute the root fid */
     if (!cm_freelanceEnabled) {
-        cm_rootFid.cell = cm_rootCellp->cellID;
-        cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
-        cm_rootFid.vnode = 1;
-        cm_rootFid.unique = 1;
+        cm_data.rootFid.cell = cm_data.rootCellp->cellID;
+        cm_data.rootFid.volume = cm_GetROVolumeID(cm_data.rootVolumep);
+        cm_data.rootFid.vnode = 1;
+        cm_data.rootFid.unique = 1;
     }
     else
-        cm_FakeRootFid(&cm_rootFid);
+        cm_FakeRootFid(&cm_data.rootFid);
         
-    code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
+    code = cm_GetSCache(&cm_data.rootFid, &cm_data.rootSCachep, cm_rootUserp, &req);
     afsi_log("cm_GetSCache code %x scache %x", code,
-             (code ? (cm_scache_t *)-1 : cm_rootSCachep));
+             (code ? (cm_scache_t *)-1 : cm_data.rootSCachep));
     if (code != 0) {
         *reasonP = "unknown error";
         return -1;
     }
 
     cm_InitDaemon(numBkgD);
-    afsi_log("cm_InitDaemon");
+    afsi_log("cm_InitDaemon complete");
 
     return 0;
 }
@@ -1048,7 +1204,7 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
     DWORD dwValue;
     DWORD code;
 
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         dummyLen = sizeof(DWORD);
index cdd9ffe..7ae3e08 100644 (file)
@@ -581,11 +581,11 @@ int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock)
        /* setup early variables */
        /* These both used to be configurable. */
        smb_UseV3 = 1;
-        buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
+        buf_blockSize = CM_CONFIGDEFAULT_BLOCKSIZE;
 
        /* turn from 1024 byte units into memory blocks */
-        cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
-        afs_diskCacheChunks = (diskCacheSize * 1024) / buf_bufferSize;
+        cacheBlocks = (cacheSize * 1024) / buf_blockSize;
+        afs_diskCacheChunks = (diskCacheSize * 1024) / buf_blockSize;
         /*printf("afs_diskCacheChunks=%d\n", afs_diskCacheChunks);*/
 
         /*
index 3df1791..53d750d 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <winsock2.h>
+#include <WINNT\afsreg.h>
 
 #include <osi.h>
 
 #include <crtdbg.h>
 #endif
 
-/*
-// The following is defined if you want to receive Power notifications,
-// including Hibernation, and also subsequent flushing of AFS volumes
-//
-#define REGISTER_POWER_NOTIFICATIONS 1
-#define FLUSH_VOLUME                 1
-//
-// Check
-*/
+//#define REGISTER_POWER_NOTIFICATIONS 1
 #include "afsd_flushvol.h"
 
 extern void afsi_log(char *pattern, ...);
@@ -91,12 +84,12 @@ static void afsd_notifier(char *msgp, char *filep, long line)
     buf_ForceTrace(TRUE);
 
     afsi_log("--- begin dump ---");
-    cm_DumpSCache(afsi_file, "a");
+    cm_DumpSCache(afsi_file, "a", 0);
 #ifdef keisa
     cm_dnlcDump(afsi_file, "a");
 #endif
-    cm_DumpBufHashTable(afsi_file, "a");
-    smb_DumpVCP(afsi_file, "a");                       
+    cm_DumpBufHashTable(afsi_file, "a", 0);
+    smb_DumpVCP(afsi_file, "a", 0);                    
     afsi_log("--- end   dump ---");
     
 #ifdef DEBUG
@@ -180,12 +173,17 @@ afsd_ServiceControlHandler(DWORD ctrlCode)
         ServiceStatus.dwControlsAccepted = 0;
         SetServiceStatus(StatusHandle, &ServiceStatus);
 
-#ifdef FLUSH_VOLUME
-        afsd_ServiceFlushVolume((DWORD) lpEventData);                         
-#endif                                                                                      
+        if (ctrlCode == SERVICE_CONTROL_STOP)
+            afsi_log("SERVICE_CONTROL_STOP");
+        else
+            afsi_log("SERVICE_CONTROL_SHUTDOWN");
+
+        /* Write all dirty buffers back to server */
+        buf_CleanAndReset();
+
         /* Force trace if requested */
         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                             AFSConfigKeyName,
+                             AFSREG_CLT_SVC_PARAM_SUBKEY,
                              0, KEY_QUERY_VALUE, &parmKey);
         if (code != ERROR_SUCCESS)
             goto doneTrace;
@@ -248,13 +246,12 @@ afsd_ServiceControlHandlerEx(
         ServiceStatus.dwControlsAccepted = 0;
         SetServiceStatus(StatusHandle, &ServiceStatus);
 
-#ifdef FLUSH_VOLUME
-        afsd_ServiceFlushVolume((DWORD) lpEventData);                         
-#endif                                                                                      
+        /* Write all dirty buffers back to server */
+        buf_CleanAndReset();
 
         /* Force trace if requested */
         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                            AFSConfigKeyName,
+                            AFSREG_CLT_SVC_PARAM_SUBKEY,
                             0, KEY_QUERY_VALUE, &parmKey);
         if (code != ERROR_SUCCESS)
             goto doneTrace;
@@ -283,13 +280,15 @@ afsd_ServiceControlHandlerEx(
         ServiceStatus.dwWaitHint = 0;
         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
         SetServiceStatus(StatusHandle, &ServiceStatus);
+        afsi_log("SERVICE_CONTROL_INTERROGATE");
         dwRet = NO_ERROR;
         break;
 
         /* XXX handle system shutdown */
         /* XXX handle pause & continue */
     case SERVICE_CONTROL_POWEREVENT:                                              
-        {                                                                                     
+        { 
+            afsi_log("SERVICE_CONTROL_POWEREVENT");
             /*                                                                                
             ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST               
             ** Return NO_ERROR == return TRUE for that message, i.e. accept request          
@@ -299,29 +298,59 @@ afsd_ServiceControlHandlerEx(
             if (powerEventsRegistered) {
                 switch((int) dwEventType)                                                         
                 {                                                                               
-                case PBT_APMQUERYSUSPEND:                                                         
+                case PBT_APMQUERYSUSPEND:       
+                    afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND"); 
+                    /* Write all dirty buffers back to server */
+                    buf_CleanAndReset();
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMQUERYSTANDBY:                                                         
-
-#ifdef FLUSH_VOLUME
-                    /* handle event */                                                            
-                    dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);                         
-#else                                                                                       
+                    afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY"); 
+                    /* Write all dirty buffers back to server */
+                    buf_CleanAndReset();
                     dwRet = NO_ERROR;                                                             
-#endif                                                                                      
                     break;                                                                        
                                                                                                                          
                     /* allow remaining case PBT_WhatEver */                                           
-                case PBT_APMSUSPEND:                                                              
-                case PBT_APMSTANDBY:                                                              
-                case PBT_APMRESUMECRITICAL:                                                       
+                case PBT_APMSUSPEND:                         
+                    afsi_log("SERVICE_CONTROL_APMSUSPEND"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
+                case PBT_APMSTANDBY:                  
+                    afsi_log("SERVICE_CONTROL_APMSTANDBY"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
+                case PBT_APMRESUMECRITICAL:             
+                    afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMRESUMESUSPEND:                                                        
+                    afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMRESUMESTANDBY:                                                        
+                    afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMBATTERYLOW:                                                           
+                    afsi_log("SERVICE_CONTROL_APMBATTERYLOW"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMPOWERSTATUSCHANGE:                                                    
+                    afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMOEMEVENT:                                                             
+                    afsi_log("SERVICE_CONTROL_APMOEMEVENT"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 case PBT_APMRESUMEAUTOMATIC:                                                      
+                    afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC"); 
+                    dwRet = NO_ERROR;                       
+                    break;                                  
                 default:                                                                          
-                    dwRet = NO_ERROR;                                                             
+                    afsi_log("SERVICE_CONTROL_unknown"); 
+                    dwRet = NO_ERROR;                       
                 }   
             }
         }
@@ -348,7 +377,7 @@ static void MountGlobalDrives(void)
     char szSubMount[256];
     DWORD dwType;
 
-    sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
+    sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
 
     dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
     if (dwResult != ERROR_SUCCESS)
@@ -410,7 +439,7 @@ static void DismountGlobalDrives()
     char szSubMount[256];
     DWORD dwType;
 
-    sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
+    sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
 
     dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
     if (dwResult != ERROR_SUCCESS)
@@ -853,7 +882,7 @@ BOOL AFSModulesVerify(void)
 
 
     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
-                        "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters",
+                        AFSREG_CLT_SVC_PARAM_SUBKEY,
                         0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         dummyLen = sizeof(cacheSize);
@@ -862,7 +891,7 @@ BOOL AFSModulesVerify(void)
         RegCloseKey (parmKey);
     }
 
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client",
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         dummyLen = sizeof(verifyServiceSig);
@@ -972,7 +1001,8 @@ typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc   )(  LPCTSTR ,
 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
 RegisterServiceCtrlHandlerFunc   pRegisterServiceCtrlHandler   = NULL; 
 
-VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
+VOID WINAPI
+afsd_Main(DWORD argc, LPTSTR *argv)
 {
     long code;
     char *reason;
@@ -1025,7 +1055,7 @@ VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
     ServiceStatus.dwCheckPoint = 1;
     ServiceStatus.dwWaitHint = 30000;
     /* accept Power Events */
-    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
+    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
     SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
 
@@ -1045,7 +1075,8 @@ VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
         int bpower = TRUE;
 
         /* see if we should handle power notifications */
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hkParm);
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 
+                            0, KEY_QUERY_VALUE, &hkParm);
         if (code == ERROR_SUCCESS) {
             dummyLen = sizeof(bpower);
             code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
@@ -1112,7 +1143,7 @@ VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
             ServiceStatus.dwCheckPoint = 2;
             ServiceStatus.dwWaitHint = 20000;
             /* accept Power Events */
-            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
+            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
             SetServiceStatus(StatusHandle, &ServiceStatus);
         }
     }
@@ -1175,6 +1206,8 @@ VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
 
     WaitForSingleObject(WaitToTerminate, INFINITE);
 
+    afsi_log("Received Termination Signal, Stopping Service");
+
     {   
         HANDLE h; char *ptbuf[1];
        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
@@ -1184,11 +1217,29 @@ VOID WINAPI afsd_Main(DWORD argc, LPTSTR *argv)
         DeregisterEventSource(h);
     }
 
+#ifdef AFS_FREELANCE_CLIENT
+    cm_FreelanceShutdown();
+    afsi_log("Freelance Shutdown complete");
+#endif
+
     DismountGlobalDrives();
-    smb_Shutdown();
-    rx_Finalize();
-    RpcShutdown();
-    buf_Shutdown();
+    afsi_log("Global Drives dismounted");
+                                         
+    cm_DaemonShutdown();                 
+    afsi_log("Daemon shutdown complete");
+                                         
+    buf_Shutdown();                      
+    afsi_log("Buffer shutdown complete");
+                                         
+    rx_Finalize();                       
+    afsi_log("rx finalization complete");
+                                         
+    smb_Shutdown();                      
+    afsi_log("smb shutdown complete");   
+                                         
+    RpcShutdown();                       
+
+    cm_ShutdownMappedMemory();           
 
 #ifdef REGISTER_POWER_NOTIFICATIONS
     /* terminate thread used to flush cache */
@@ -1214,13 +1265,33 @@ DWORD __stdcall afsdMain_thread(void* notUsed)
     return(0);
 }
 
+void usage(void)
+{
+    fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
+}
+
 int
-main(void)
+main(int argc, char * argv[])
 {
     static SERVICE_TABLE_ENTRY dispatchTable[] = {
         {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
         {NULL, NULL}
     };
+    int i;
+
+    for (i = 1; i < argc; i++) {
+        if (!stricmp(argv[i],"--validate-cache")) {
+            if (++i != argc - 1) {
+                usage();
+                return(1);
+            }
+
+            return cm_ValidateMappedMemory(argv[i]);
+        } else {
+            usage();
+            return(1);
+        }
+    }
 
     if (!StartServiceCtrlDispatcher(dispatchTable))
     {
index 4cf9a0e..c9c8a06 100644 (file)
@@ -13,8 +13,8 @@
 #define AFS_VERINFO_NAME "afsd_service"
 #define AFS_VERINFO_FILENAME "afsd_service.exe"
 
-1      ICON    afsd.ico
-
 #include "AFS_component_version_number.h"
 #include "..\..\config\NTVersioninfo.rc"
 
+1       ICON    afsd.ico
+
diff --git a/src/WINNT/afsd/afsdacl.c b/src/WINNT/afsd/afsdacl.c
new file mode 100644 (file)
index 0000000..f669a45
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+
+Copyright 2004 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+/* $Id */
+
+#include<windows.h>
+#include<aclapi.h>
+#include<sddl.h>
+#include<stdio.h>
+#include<string.h>
+
+#define SETDACL     1
+#define RESETDACL   2
+
+#define AFSSERVICE                  "TransarcAFSDaemon"
+#define AFSCLIENT_ADMIN_GROUPNAME   "AFS Client Admins"
+#define EVERYONE_GROUPNAME          "Everyone"
+
+char * progname = NULL;
+
+void show_usage(void) {
+    fprintf(stderr,
+        "%s : Set or reset the DACL to allow starting or stopping\n"
+        "     the afsd service by any ordinary user.\n"
+        "\n"
+        "Usage : %s [-set | -reset] [-show]\n"
+        "      -set   : Sets the DACL\n"
+        "      -reset : Reset the DACL\n"
+        "      -show  : Show current DACL (SDSF)\n"
+        , progname, progname);
+}
+
+void show_last_error(DWORD code) {
+   LPVOID lpvMessageBuffer;
+
+   if(!code)
+        code = GetLastError();
+
+   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                 FORMAT_MESSAGE_FROM_SYSTEM,
+                 NULL, code,
+                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                (LPTSTR)&lpvMessageBuffer, 0, NULL);
+
+   fprintf(stderr,
+       "%s: Error %d : %s\n",
+       progname,
+       code,
+       (LPSTR) lpvMessageBuffer);
+
+   LocalFree(lpvMessageBuffer);
+}
+
+int set_dacl(int action) {
+    int             rv = 1;
+    BOOL            bDaclPresent = FALSE;
+    BOOL            bDaclDefaulted = FALSE;
+    SC_HANDLE       scm = NULL;
+    SC_HANDLE       s_afs = NULL;
+    PSECURITY_DESCRIPTOR psdesc = NULL;
+    PACL            pacl = NULL;
+    PACL            pnewacl = NULL;
+    EXPLICIT_ACCESS exa[2];
+    DWORD           dwSize = 0;
+    DWORD           code = ERROR_SUCCESS;
+    SECURITY_DESCRIPTOR sd;
+
+    scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+    if(!scm) {
+        show_last_error(0);
+        goto exit0;
+    }
+
+    s_afs = OpenService(scm, AFSSERVICE, READ_CONTROL | WRITE_DAC);
+    if(!s_afs) {
+        show_last_error(0);
+        goto exit0;
+    }
+
+    if (!QueryServiceObjectSecurity(s_afs, DACL_SECURITY_INFORMATION, 
+        &sd, 0, &dwSize))
+    {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {
+            psdesc = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
+                HEAP_ZERO_MEMORY, dwSize);
+            if (psdesc == NULL)
+            {
+                show_last_error(0);
+                goto exit0;
+            }
+
+            if (!QueryServiceObjectSecurity(s_afs,
+                DACL_SECURITY_INFORMATION, psdesc, dwSize, &dwSize)) {
+                show_last_error(0);
+                goto exit0;
+                }
+        }
+        else {
+            show_last_error(0);
+            goto exit0;
+        }
+    }
+    /* else : shouldn't happen. */
+
+    if (!GetSecurityDescriptorDacl(psdesc, &bDaclPresent, &pacl, &bDaclDefaulted))
+        show_last_error(0);
+
+    BuildExplicitAccessWithName(&exa[0], AFSCLIENT_ADMIN_GROUPNAME,
+        SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, 
+        SET_ACCESS,
+        NO_INHERITANCE);
+
+    BuildExplicitAccessWithName(&exa[1], EVERYONE_GROUPNAME,
+        SERVICE_START | SERVICE_STOP | READ_CONTROL,
+        ((action==RESETDACL)?REVOKE_ACCESS:SET_ACCESS),
+        NO_INHERITANCE);
+
+    code = SetEntriesInAcl(2, exa, pacl, &pnewacl);
+    if(code != ERROR_SUCCESS) {
+        show_last_error(code);
+    }
+
+    if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+        show_last_error(0);
+
+    if(!SetSecurityDescriptorDacl(&sd, TRUE, pnewacl, FALSE))
+        show_last_error(0);
+
+    if (!SetServiceObjectSecurity(s_afs, DACL_SECURITY_INFORMATION, &sd))
+        show_last_error(0);
+
+exit0:
+    if(pnewacl)
+        LocalFree(pnewacl);
+    if(psdesc)
+        HeapFree(GetProcessHeap(), 0, psdesc);
+    if(s_afs)
+        CloseServiceHandle(s_afs);
+    if(scm)
+        CloseServiceHandle(scm);
+
+    return rv;
+}
+
+int show_dacl(void) {
+    int             rv = 1;
+    BOOL            bDaclPresent = FALSE;
+    BOOL            bDaclDefaulted = FALSE;
+    SC_HANDLE       scm = NULL;
+    SC_HANDLE       s_afs = NULL;
+    PSECURITY_DESCRIPTOR psdesc = NULL;
+    DWORD           dwSize = 0;
+    DWORD           code = ERROR_SUCCESS;
+    SECURITY_DESCRIPTOR sd;
+    LPSTR           pstr = NULL;
+
+    scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+    if(!scm) {
+        show_last_error(0);
+        goto exit0;
+    }
+
+    s_afs = OpenService(scm, AFSSERVICE, READ_CONTROL);
+    if(!s_afs) {
+        show_last_error(0);
+        goto exit0;
+    }
+
+    if (!QueryServiceObjectSecurity(s_afs, DACL_SECURITY_INFORMATION,
+        &sd, 0, &dwSize))
+    {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {
+            psdesc = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
+                HEAP_ZERO_MEMORY, dwSize);
+            if (psdesc == NULL)
+            {
+                show_last_error(0);
+                goto exit0;
+            }
+
+            if (!QueryServiceObjectSecurity(s_afs,
+                DACL_SECURITY_INFORMATION, psdesc, dwSize, &dwSize)) {
+                show_last_error(0);
+                goto exit0;
+                }
+        }
+        else {
+            show_last_error(0);
+            goto exit0;
+        }
+    }
+    /* else : shouldn't happen. */
+
+    if(!ConvertSecurityDescriptorToStringSecurityDescriptor(
+        psdesc,
+        SDDL_REVISION_1,
+        DACL_SECURITY_INFORMATION,
+        &pstr,
+        NULL)) 
+    {
+        show_last_error(0);
+        goto exit0;
+    }
+
+    printf("DACL for AFSD service is : [%s]\n",pstr);
+
+exit0:
+    if(pstr)
+        LocalFree(pstr);
+    if(psdesc)
+        HeapFree(GetProcessHeap(), 0, psdesc);
+    if(s_afs)
+        CloseServiceHandle(s_afs);
+    if(scm)
+        CloseServiceHandle(scm);
+
+    return rv;
+}
+
+int main(int argc, char ** argv) {
+    int showdacl = FALSE;
+    int action = 0;
+    int i;
+    int rv;
+
+    progname = argv[0];
+
+    for(i=1; i<argc; i++) {
+        if(!strcmp(argv[i],"-set") && !action)
+            action = SETDACL;
+        else if(!strcmp(argv[i], "-reset") && !action)
+            action = RESETDACL;
+        else if(!strcmp(argv[i], "-show"))
+            showdacl = TRUE;
+        else {
+            show_usage();
+            return 1;
+        }
+    }
+
+    if(!showdacl && action == 0) {
+        show_usage();
+        return 1;
+    }
+
+    if(action) {
+        rv = set_dacl(action);
+    }
+    
+    if(showdacl) {
+        rv = show_dacl();
+    }
+
+    return rv;
+}
diff --git a/src/WINNT/afsd/afsdacl.rc b/src/WINNT/afsd/afsdacl.rc
new file mode 100644 (file)
index 0000000..079b4f4
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Define VERSIONINFO resource */
+
+#define  AFS_VERINFO_FILE_DESCRIPTION "AFS Service DACL Admin Tool"
+#define AFS_VERINFO_NAME "afsdacl"
+#define AFS_VERINFO_FILENAME "afsdacl.exe"
+
+#include "AFS_component_version_number.h"
+#include "..\..\config\NTVersioninfo.rc"
index 69bd6bd..a1fc846 100644 (file)
@@ -65,6 +65,8 @@
 #include <afs/ptserver.h>
 #include <afs/ptuser.h>
 
+#include <WINNT\afsreg.h>
+
 /*
  * TIMING _____________________________________________________________________
  *
@@ -228,6 +230,11 @@ FUNC_INFO leash_fi[] = {
     END_FUNC_INFO
 };
 
+FUNC_INFO leash_opt_fi[] = {
+    MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
+    END_FUNC_INFO
+};
+
 FUNC_INFO k5_fi[] = {
     MAKE_FUNC_INFO(krb5_change_password),
     MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
@@ -282,6 +289,7 @@ FUNC_INFO k5_fi[] = {
     MAKE_FUNC_INFO(krb5_get_default_config_files),
     MAKE_FUNC_INFO(krb5_free_config_files),
     MAKE_FUNC_INFO(krb5_get_default_realm),
+    MAKE_FUNC_INFO(krb5_free_default_realm),
     MAKE_FUNC_INFO(krb5_free_ticket),
     MAKE_FUNC_INFO(krb5_decode_ticket),
     MAKE_FUNC_INFO(krb5_get_host_realm),
@@ -371,6 +379,7 @@ static HINSTANCE hComErr = 0;
 static HINSTANCE hService = 0;
 static HINSTANCE hProfile = 0;
 static HINSTANCE hLeash = 0;
+static HINSTANCE hLeashOpt = 0;
 static HINSTANCE hCCAPI = 0;
 static struct principal_ccache_data * princ_cc_data = NULL;
 static struct cell_principal_map    * cell_princ_map = NULL;
@@ -407,6 +416,7 @@ KFW_initialize(void)
             LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
             LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
             LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+            LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
 
             if ( KFW_is_available() ) {
                 char rootcell[MAXCELLCHARS+1];
@@ -429,32 +439,32 @@ KFW_initialize(void)
 void
 KFW_cleanup(void)
 {
-    if (hKrb5)
-        FreeLibrary(hKrb5);
-#ifdef USE_KRB4
-    if (hKrb4)
-        FreeLibrary(hKrb4);
-#endif /* USE_KRB4 */
-    if (hProfile)
-        FreeLibrary(hProfile);
-    if (hComErr)
-        FreeLibrary(hComErr);
-    if (hService)
-        FreeLibrary(hService);
+    if (hLeashOpt)
+        FreeLibrary(hLeashOpt);
+    if (hCCAPI)
+        FreeLibrary(hCCAPI);
+    if (hLeash)
+        FreeLibrary(hLeash);
+    if (hKrb524)
+        FreeLibrary(hKrb524);
 #ifdef USE_MS2MIT
     if (hSecur32)
         FreeLibrary(hSecur32);
 #endif /* USE_MS2MIT */
-    if (hKrb524)
-        FreeLibrary(hKrb524);
-    if (hLeash)
-        FreeLibrary(hLeash);
-    if (hCCAPI)
-        FreeLibrary(hCCAPI);
+    if (hService)
+        FreeLibrary(hService);
+    if (hComErr)
+        FreeLibrary(hComErr);
+    if (hProfile)
+        FreeLibrary(hProfile);
+#ifdef USE_KRB4
+    if (hKrb4)
+        FreeLibrary(hKrb4);
+#endif /* USE_KRB4 */
+    if (hKrb5)
+        FreeLibrary(hKrb5);
 }
 
-static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
-
 int
 KFW_use_krb524(void)
 {
@@ -462,7 +472,7 @@ KFW_use_krb524(void)
     DWORD code, len;
     DWORD use524 = 0;
 
-    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(use524);
@@ -471,7 +481,7 @@ KFW_use_krb524(void)
         RegCloseKey(parmKey);
     }
     if (code != ERROR_SUCCESS) {
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                              0, KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(use524);
@@ -490,7 +500,7 @@ KFW_is_available(void)
     DWORD code, len;
     DWORD enableKFW = 1;
 
-    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(enableKFW);
@@ -500,7 +510,7 @@ KFW_is_available(void)
     }
     
     if (code != ERROR_SUCCESS) {
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                              0, KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(enableKFW);
@@ -930,7 +940,7 @@ KFW_import_windows_lsa(void)
     code = pkrb5_cc_get_principal(ctx, cc, &princ);
     if ( code ) goto cleanup;
 
-    dwMsLsaImport = pLeash_get_default_mslsa_import();
+    dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
     switch ( dwMsLsaImport ) {
     case 0: /* do not import */
         goto cleanup;
@@ -1230,8 +1240,9 @@ KFW_AFS_get_cred( char * username,
     if ( code ) goto cleanup;
 
     realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
+
     userrealm = strchr(username,'@');
-    if (userrealm) {
+    if ( userrealm ) {
         pname = strdup(username);
         userrealm = strchr(pname, '@');
         *userrealm = '\0';
@@ -1254,7 +1265,6 @@ KFW_AFS_get_cred( char * username,
         strcat(pname,"@");
         strcat(pname,realm);
     }
-
     if ( IsDebuggerPresent() ) {
         OutputDebugString("Realm: ");
         OutputDebugString(realm);
@@ -2660,7 +2670,7 @@ KFW_AFS_klog(
         goto skip_krb5_init;
     }
 
-    /* lookfor client principals which cannot be distinguished 
+    /* look for client principals which cannot be distinguished 
      * from Kerberos 4 multi-component principal names
      */
     k5data = krb5_princ_component(ctx,client_principal,0);
index 746c6cc..a16a45f 100644 (file)
@@ -27,6 +27,8 @@
 #include "krb.h"
 #include "afskfw.h"
 
+#include <WINNT\afsreg.h>
+
 DWORD TraceOption = 0;
 
 HANDLE hDLL;
@@ -339,13 +341,13 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     } else
         effDomain = NULL;
 
-    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY, 0, KEY_READ, &hkParm );
+    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
     if(rv != ERROR_SUCCESS) {
         hkParm = NULL;
         DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
     }
 
-    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CLIENT_PROVIDER_KEY, 0, KEY_READ, &hkNp );
+    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
     if(rv != ERROR_SUCCESS) {
         hkNp = NULL;
         DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
@@ -533,6 +535,48 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         if(regexscript) free(regexscript);
     }
 
+    DebugEvent("Looking up TheseCells");
+    /* Logon script */
+    /* First find out where the key is */
+    hkTemp = NULL;
+    rv = ~ERROR_SUCCESS;
+    dwType = 0;
+    if (hkDom)
+        rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
+        hkTemp = hkDom;
+        DebugEvent("Located TheseCells in hkDom");
+    } else if (hkDoms)
+        rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+        hkTemp = hkDoms;
+        DebugEvent("Located TheseCells in hkDoms");
+    } else if (hkNp)
+        rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+        hkTemp = hkNp;
+        DebugEvent("Located TheseCells in hkNp");
+    }
+
+    if (hkTemp) {
+        HRESULT hr;
+        size_t len;
+        CHAR * thesecells;
+
+        /* dwSize still has the size of the required buffer in bytes. */
+        thesecells = malloc(dwSize);
+        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, (LPBYTE) thesecells, &dwSize);
+        if(rv != ERROR_SUCCESS) {/* what the ..? */
+            DebugEvent("Can't look up TheseCells [%d]",rv);
+            goto doneTheseCells;
+        }
+
+        DebugEvent("Found TheseCells [%s]", thesecells);
+        opt->theseCells = thesecells;
+
+      doneTheseCells:;
+    }
+
   cleanup:
     if(hkNp) RegCloseKey(hkNp);
     if(hkDom) RegCloseKey(hkDom);
@@ -611,7 +655,7 @@ DWORD APIENTRY NPLogonNotify(
     DWORD code;
 
     int pw_exp;
-    char *reason = 0;
+    char *reason;
     char *ctemp;
 
     BOOLEAN interactive;
@@ -662,7 +706,7 @@ DWORD APIENTRY NPLogonNotify(
         }
     }
 
-    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
+    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &NPKey);
     LSPsize=sizeof(TraceOption);
     RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
@@ -739,27 +783,40 @@ DWORD APIENTRY NPLogonNotify(
                
         /* if Integrated Logon  */
         if (ISLOGONINTEGRATED(opt.LogonOption))
-        {      
+        {                      
             if ( KFW_is_available() ) {
                 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
-                DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
-                           uname,opt.smbName,cell,code);
+                DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",uname,opt.smbName,cell,code);
+                if (code == 0 && opt.theseCells) { 
+                    char * principal, *p;
+
+                    principal = (char *)malloc(strlen(uname) + strlen(cell) + 2);
+                    if ( principal ) {
+                        strcpy(principal, uname);
+                        p = principal + strlen(uname);
+                        *p++ = '@';
+                        strcpy(p, cell);
+                        for ( ;*p; p++) {
+                            *p = toupper(*p);
+                        }
+
+                        p = opt.theseCells;
+                        while ( *p ) {
+                            code = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
+                            DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
+                                        principal,opt.smbName,p,code);
+                            p += strlen(p) + 1;
+                        }
+                        
+                        free(principal);
+                    }
+                }
             } else {
                 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
                                                     uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
                                                     &reason);
-
-                DebugEvent("AFS AfsLogon - ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s] Reason[%s]",
-                            code,uname,cell,reason ? reason : "<none>");
-                {
-                    char msg[2048];
-                    sprintf(msg, "Code[%x] uname[%s] Cell[%s] Reason[%s]",
-                            code,uname,cell,reason ? reason : "<none>");
-                    MessageBox(hwndOwner,
-                                msg,
-                                "AFS Logon",
-                                MB_ICONINFORMATION | MB_OK);
-                }
+                DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x] uname[%s] Cell[%s]",
+                            code,uname,cell);
             }       
             if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
                 for ( ctemp = uname; *ctemp ; ctemp++) {
@@ -770,13 +827,15 @@ DWORD APIENTRY NPLogonNotify(
             }
 
             /* is service started yet?*/
+
             /* If we've failed because the client isn't running yet and the
             * client is set to autostart (and therefore it makes sense for
             * us to wait for it to start) then sleep a while and try again. 
             * If the error was something else, then give up. */
             if (code != KTC_NOCM && code != KTC_NOCMRPC || !afsWillAutoStart)
                 break;
-        } else {  
+        }
+        else {  
             /*JUST check to see if its running*/
             if (IsServiceRunning())
                 break;
@@ -845,7 +904,8 @@ DWORD APIENTRY NPLogonNotify(
         }
     }
 
-    if(opt.smbName) free(opt.smbName);
+    if (opt.theseCells) free(opt.theseCells);
+    if (opt.smbName) free(opt.smbName);
 
     DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
     return code;
@@ -909,7 +969,7 @@ VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
     /* Make sure the AFS Libraries are initialized */
     AfsLogonInit();
 
-    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
+    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                         0, KEY_QUERY_VALUE, &NPKey);
     LSPsize=sizeof(TraceOption);
     RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
index 120be6b..c37e438 100644 (file)
@@ -32,15 +32,14 @@ SOFTWARE.
 #include <strsafe.h>
 
 
-#define REG_CLIENT_PARMS_KEY            "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
-#define REG_CLIENT_PROVIDER_KEY                        "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider"
-#define REG_CLIENT_DOMAINS_SUBKEY              "Domain"
+#define REG_CLIENT_DOMAINS_SUBKEY      "Domain"
 #define REG_CLIENT_RETRY_INTERVAL_PARM  "LoginRetryInterval"
 #define REG_CLIENT_SLEEP_INTERVAL_PARM "LoginSleepInterval"
 #define REG_CLIENT_FAIL_SILENTLY_PARM   "FailLoginsSilently"
 #define REG_CLIENT_TRACE_OPTION_PARM   "TraceOption"
 #define REG_CLIENT_LOGON_OPTION_PARM   "LogonOptions"
 #define REG_CLIENT_LOGON_SCRIPT_PARMW  L"LogonScript"
+#define REG_CLIENT_THESE_CELLS_PARM     "TheseCells"
 #define DEFAULT_RETRY_INTERVAL          60                        /* seconds*/
 #define DEFAULT_FAIL_SILENTLY           FALSE
 #define DEFAULT_SLEEP_INTERVAL          5                         /* seconds*/
@@ -64,11 +63,12 @@ extern DWORD TraceOption;
 typedef struct LogonOptions_type {
        DWORD   LogonOption;
        BOOLEAN failSilently;
-       int             retryInterval;
-       int             sleepInterval;
+       int     retryInterval;
+       int     sleepInterval;
        char *  smbName;
        LPWSTR  logonScript;
        DWORD   flags; /* LOGON_FLAG_* */
+        char *  theseCells;
 } LogonOptions_t;
 
 /* */
index 6ef60a0..843f345 100644 (file)
@@ -13,6 +13,8 @@
 #include <windows.h>
 #include <stdio.h>
 
+#include <WINNT\afsreg.h>
+
 int
 main(int argc, char **argv) {
     BOOL res;
@@ -27,7 +29,7 @@ main(int argc, char **argv) {
     }
 
     if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
-                        "SOFTWARE\\OpenAFS\\Client\\Submounts",
+                        AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
                         0,
                         NULL,
                         REG_OPTION_NON_VOLATILE,
@@ -45,7 +47,7 @@ main(int argc, char **argv) {
             }
         } else {
             if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
-                                "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters",
+                                AFSREG_CLT_SVC_PARAM_SUBKEY,
                                 0,
                                 NULL,
                                 REG_OPTION_NON_VOLATILE,
index 423bdd3..91f3efe 100644 (file)
@@ -219,7 +219,7 @@ int RXAFS_Lookup (struct rx_connection *,
 #define CM_ERROR_EXISTS                        (CM_ERROR_BASE+11)
 #define CM_ERROR_CROSSDEVLINK          (CM_ERROR_BASE+12)
 #define CM_ERROR_BADOP                 (CM_ERROR_BASE+13)
-#define CM_ERROR_BADPASSWORD    (CM_ERROR_BASE+14)
+#define CM_ERROR_BADPASSWORD            (CM_ERROR_BASE+14)
 #define CM_ERROR_NOTDIR                        (CM_ERROR_BASE+15)
 #define CM_ERROR_ISDIR                 (CM_ERROR_BASE+16)
 #define CM_ERROR_READONLY              (CM_ERROR_BASE+17)
@@ -250,4 +250,5 @@ int RXAFS_Lookup (struct rx_connection *,
 #define CM_ERROR_GSSCONTINUE            (CM_ERROR_BASE+43)
 #define CM_ERROR_TIDIPC                 (CM_ERROR_BASE+44)
 #define CM_ERROR_TOO_MANY_SYMLINKS      (CM_ERROR_BASE+45)
+#define CM_ERROR_PATH_NOT_COVERED       (CM_ERROR_BASE+46)
 #endif /*  __CM_H_ENV__ */
index ac4cc02..b7c50ae 100644 (file)
  * things, since we can always lose the race condition getting to the parent vnode.
  */
 int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, long rights,
-       long *outRightsp)
+                        long *outRightsp)
 {
-       cm_scache_t *aclScp;
-        long code;
-        cm_fid_t tfid;
-        int didLock;
-        long trights;
+    cm_scache_t *aclScp;
+    long code;
+    cm_fid_t tfid;
+    int didLock;
+    long trights;
        
-       didLock = 0;
-       if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
-               aclScp = scp;
-                cm_HoldSCache(scp);
-       }
-        else {
-               tfid.cell = scp->fid.cell;
-               tfid.volume = scp->fid.volume;
-                tfid.vnode = scp->parentVnode;
-                tfid.unique = scp->parentUnique;
-               aclScp = cm_FindSCache(&tfid);
-                if (!aclScp) return 0;
-                if (aclScp != scp) {
-                       code = lock_TryMutex(&aclScp->mx);
-                       if (code == 0) {
-                               /* can't get lock safely and easily */
-                               cm_ReleaseSCache(aclScp);
-                               return 0;
-                       }
+    didLock = 0;
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+        aclScp = scp;
+        cm_HoldSCache(scp);
+    } else {
+        tfid.cell = scp->fid.cell;
+        tfid.volume = scp->fid.volume;
+        tfid.vnode = scp->parentVnode;
+        tfid.unique = scp->parentUnique;
+        aclScp = cm_FindSCache(&tfid);
+        if (!aclScp) 
+            return 0;
+        if (aclScp != scp) {
+            code = lock_TryMutex(&aclScp->mx);
+            if (code == 0) {
+                /* can't get lock safely and easily */
+                cm_ReleaseSCache(aclScp);
+                return 0;
+            }
 
-                       /* check that we have a callback, too */
-                        if (!cm_HaveCallback(aclScp)) {
-                               /* can't use it */
-                                lock_ReleaseMutex(&aclScp->mx);
-                                cm_ReleaseSCache(aclScp);
-                                return 0;
-                        }
-                        didLock = 1;
-               }
-       }
+            /* check that we have a callback, too */
+            if (!cm_HaveCallback(aclScp)) {
+                /* can't use it */
+                lock_ReleaseMutex(&aclScp->mx);
+                cm_ReleaseSCache(aclScp);
+                return 0;
+            }
+            didLock = 1;
+        }
+    }
 
-       lock_AssertMutex(&aclScp->mx);
+    lock_AssertMutex(&aclScp->mx);
         
-        /* now if rights is a subset of the public rights, we're done.
-        * Otherwise, if we an explicit acl entry, we're also in good shape,
-        * and can definitively answer.
-         */
-       if ((~aclScp->anyAccess & rights) == 0) {
-               *outRightsp = rights;
-        }
-        else {
-               /* we have to check the specific rights info */
-                code = cm_FindACLCache(aclScp, up, &trights);
-                if (code) {
-                       code = 0;
-                        goto done;
-                }
-                *outRightsp = trights;
+    /* now if rights is a subset of the public rights, we're done.
+     * Otherwise, if we an explicit acl entry, we're also in good shape,
+     * and can definitively answer.
+     */
+    if ((~aclScp->anyAccess & rights) == 0) {
+        *outRightsp = rights;
+    } else {
+        /* we have to check the specific rights info */
+        code = cm_FindACLCache(aclScp, up, &trights);
+        if (code) {
+            code = 0;
+            goto done;
         }
+        *outRightsp = trights;
+    }
 
-       /* check mode bits */
-       if (!(scp->unixModeBits & 0400))
-               *outRightsp &= ~PRSFS_READ;
-       if (!(scp->unixModeBits & 0200))
-               *outRightsp &= ~PRSFS_WRITE;
+    /* check mode bits */
+    if (!(scp->unixModeBits & 0400))
+        *outRightsp &= ~PRSFS_READ;
+    if (!(scp->unixModeBits & 0200))
+        *outRightsp &= ~PRSFS_WRITE;
 
-        code = 1;
-        /* fall through */
-        
-done:
+    code = 1;
+    /* fall through */
+
+  done:
     if (didLock) 
         lock_ReleaseMutex(&aclScp->mx);
-        cm_ReleaseSCache(aclScp);
-        return code;
+    cm_ReleaseSCache(aclScp);
+    return code;
 }
 
 /* called with locked scp; ensures that we have an ACL cache entry for the
@@ -115,47 +114,46 @@ done:
  * succeed.
  */
 long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
-       struct cm_req *reqp)
+                        struct cm_req *reqp)
 {
-       long code;
-       cm_fid_t tfid;
+    long code;
+    cm_fid_t tfid;
     cm_scache_t *aclScp;
 
-       /* pretty easy: just force a pass through the fetch status code */
+    /* pretty easy: just force a pass through the fetch status code */
         
-       osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
+    osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
 
     /* first, start by finding out whether we have a directory or something
-        * else, so we can find what object's ACL we need.
+     * else, so we can find what object's ACL we need.
      */
     code = cm_SyncOp(scp, NULL, up, reqp, 0, CM_SCACHESYNC_GETSTATUS
                       | CM_SCACHESYNC_NEEDCALLBACK);
-                        
-    if (code) return code;
+    if (code) 
+        return code;
         
     if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
-               /* not a dir, use parent dir's acl */
-               tfid.cell = scp->fid.cell;
+        /* not a dir, use parent dir's acl */
+        tfid.cell = scp->fid.cell;
         tfid.volume = scp->fid.volume;
         tfid.vnode = scp->parentVnode;
         tfid.unique = scp->parentUnique;
-               lock_ReleaseMutex(&scp->mx);
-               code = cm_GetSCache(&tfid, &aclScp, up, reqp);
+        lock_ReleaseMutex(&scp->mx);
+        code = cm_GetSCache(&tfid, &aclScp, up, reqp);
         if (code) {
-                       lock_ObtainMutex(&scp->mx);
+            lock_ObtainMutex(&scp->mx);
             return code;
-        }
+        }       
                 
-               osi_Log1(afsd_logp, "GetAccess parent %x", aclScp);
-               lock_ObtainMutex(&aclScp->mx);
+        osi_Log1(afsd_logp, "GetAccess parent %x", aclScp);
+        lock_ObtainMutex(&aclScp->mx);
         code = cm_GetCallback(aclScp, up, reqp, 1);
         lock_ReleaseMutex(&aclScp->mx);
         cm_ReleaseSCache(aclScp);
         lock_ObtainMutex(&scp->mx);
-    } 
-    else {
-               code = cm_GetCallback(scp, up, reqp, 1);
+    } else {
+        code = cm_GetCallback(scp, up, reqp, 1);
     }
 
-       return code;
+    return code;
 }
index 44e623c..b0f9a6d 100644 (file)
@@ -18,6 +18,7 @@
 #include <malloc.h>
 
 #include "afsd.h"
+#include <osisleep.h>
 
 /* 
  * This next lock controls access to all cm_aclent structures in the system,
  * An aclent structure is free if it has no back vnode pointer.
  */
 osi_rwlock_t cm_aclLock;               /* lock for system's aclents */
-cm_aclent_t *cm_aclLRUp;                /* LRUQ for dudes in vnode's lists */
-cm_aclent_t *cm_aclLRUEndp;             /* ditto */
 
-/* This function must be called with cm_aclLock and the aclp->back_mx held */
+/* This must be called with cm_aclLock and the aclp->back->mx held */
 static void CleanupACLEnt(cm_aclent_t * aclp)
 {
     cm_aclent_t *taclp;
     cm_aclent_t **laclpp;
-
+        
     if (aclp->backp) {
         /* 
-         * Remove the entry from the vnode's list
+         * Remove the entry from the vnode's list 
          */
         laclpp = &aclp->backp->randomACLp;
-        for ( taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp ) {
-            if (taclp == aclp)
+        for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) {
+            if (taclp == aclp) 
                 break;
         }
-        if (!taclp)
-            osi_panic("CleanupACLEnt race",__FILE__,__LINE__);
-        *laclpp = aclp->nextp;                  /* remove from the vnode's list */
+        if (!taclp) 
+            osi_panic("CleanupACLEnt race", __FILE__, __LINE__);
+        *laclpp = aclp->nextp;                 /* remove from vnode list */
         aclp->backp = NULL;
     }
 
@@ -72,27 +71,30 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
     long retval = -1;
 
     lock_ObtainWrite(&cm_aclLock);
-    *rightsp = 0;       /* get a new acl from server if we don't find a 
-                         * current entry
-                         */
+    *rightsp = 0;   /* get a new acl from server if we don't find a
+                     * current entry 
+                     */
+
     for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
         if (aclp->userp == userp) {
             if (aclp->tgtLifetime && aclp->tgtLifetime <= osi_Time()) {
                 /* ticket expired */
-                osi_QRemove((osi_queue_t **) &cm_aclLRUp, &aclp->q);
+                osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q);
                 CleanupACLEnt(aclp);
-                osi_QAddT((osi_queue_t **) &cm_aclLRUp,
-                           (osi_queue_t **) &cm_aclLRUEndp,
+
+                /* move to the tail of the LRU queue */
+                osi_QAddT((osi_queue_t **) &cm_data.aclLRUp,
+                           (osi_queue_t **) &cm_data.aclLRUEndp,
                            &aclp->q);
             } else {
                 *rightsp = aclp->randomAccess;
-                if (cm_aclLRUEndp == aclp)
-                    cm_aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
+                if (cm_data.aclLRUEndp == aclp)
+                    cm_data.aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
 
                 /* move to the head of the LRU queue */
-                osi_QRemove((osi_queue_t **) &cm_aclLRUp, &aclp->q);
-                osi_QAddH((osi_queue_t **) &cm_aclLRUp,
-                           (osi_queue_t **) &cm_aclLRUEndp,
+                osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q);
+                osi_QAddH((osi_queue_t **) &cm_data.aclLRUp,
+                           (osi_queue_t **) &cm_data.aclLRUEndp,
                            &aclp->q);
                 retval = 0;     /* success */
             }               
@@ -104,22 +106,23 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
     return retval;
 }       
 
-
 /* 
  * This function returns a free (not in the LRU queue) acl cache entry.
- * It must be called with the cm_aclLock lock held.
+ * It must be called with the cm_aclLock lock held
  */
 static cm_aclent_t *GetFreeACLEnt(void)
 {
     cm_aclent_t *aclp;
 
-    if (cm_aclLRUp == NULL)
+    if (cm_data.aclLRUp == NULL)
         osi_panic("empty aclent LRU", __FILE__, __LINE__);
 
-    aclp = cm_aclLRUEndp;
-    cm_aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
-    osi_QRemove((osi_queue_t **) &cm_aclLRUp, &aclp->q);
+    aclp = cm_data.aclLRUEndp;
+    cm_data.aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
+    osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q);
+
     CleanupACLEnt(aclp);
+
     return aclp;
 }
 
@@ -151,7 +154,7 @@ long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights)
      * someone there.
      */
     aclp = GetFreeACLEnt();             /* can't fail, panics instead */
-    osi_QAddH((osi_queue_t **) &cm_aclLRUp, (osi_queue_t **) &cm_aclLRUEndp, &aclp->q);
+    osi_QAddH((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q);
     aclp->backp = scp;
     aclp->nextp = scp->randomACLp;
     scp->randomACLp = aclp;
@@ -164,10 +167,73 @@ long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights)
     return 0;
 }
 
+long cm_ShutdownACLCache(void)
+{
+    return 0;
+}
+
+long cm_ValidateACLCache(void)
+{
+    long size = cm_data.stats * 2;
+    long count;
+    cm_aclent_t * aclp;
+
+    for ( aclp = cm_data.aclLRUp, count = 0; aclp;
+          aclp = (cm_aclent_t *) osi_QNext(&aclp->q), count++ ) {
+        if (aclp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: acpl->magic != CM_ACLENT_MAGIC\n");
+            return -1;
+        }
+        if (aclp->nextp && aclp->nextp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->nextp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr,"cm_ValidateACLCache failure: acpl->nextp->magic != CM_ACLENT_MAGIC\n");
+            return -2;
+        }
+        if (aclp->backp && aclp->backp->magic != CM_SCACHE_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->backp->magic != CM_SCACHE_MAGIC");
+            fprintf(stderr,"cm_ValidateACLCache failure: acpl->backp->magic != CM_SCACHE_MAGIC\n");
+            return -3;
+        }
+        if (count != 0 && aclp == cm_data.aclLRUp || count > size) {
+            afsi_log("cm_ValidateACLCache failure: loop in cm_data.aclLRUp list");
+            fprintf(stderr, "cm_ValidateACLCache failure: loop in cm_data.aclLRUp list\n");
+            return -4;
+        }
+    }
+
+    for ( aclp = cm_data.aclLRUEndp, count = 0; aclp;
+          aclp = (cm_aclent_t *) osi_QPrev(&aclp->q), count++ ) {
+        if (aclp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->magic != CM_ACLENT_MAGIC\n");
+            return -5;
+        }
+        if (aclp->nextp && aclp->nextp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->nextp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->nextp->magic != CM_ACLENT_MAGIC\n");
+            return -6;
+        }
+        if (aclp->backp && aclp->backp->magic != CM_SCACHE_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->backp->magic != CM_SCACHE_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->backp->magic != CM_SCACHE_MAGIC\n");
+            return -7;
+        }
+
+        if (count != 0 && aclp == cm_data.aclLRUEndp || count > size) {
+            afsi_log("cm_ValidateACLCache failure: loop in cm_data.aclLRUEndp list");
+            fprintf(stderr, "cm_ValidateACLCache failure: loop in cm_data.aclLRUEndp list\n");
+            return -8;
+        }
+    }
+
+    return 0;
+}
+
 /* 
  * Initialize the cache to have an entries.  Called during system startup.
  */
-long cm_InitACLCache(long size)
+long cm_InitACLCache(int newFile, long size)
 {
     cm_aclent_t *aclp;
     long i;
@@ -179,16 +245,26 @@ long cm_InitACLCache(long size)
     }
 
     lock_ObtainWrite(&cm_aclLock);
-    cm_aclLRUp = cm_aclLRUEndp = NULL;
-    aclp = (cm_aclent_t *) malloc(size * sizeof(cm_aclent_t));
-    memset(aclp, 0, size * sizeof(cm_aclent_t));
+    if ( newFile ) {
+        cm_data.aclLRUp = cm_data.aclLRUEndp = NULL;
+        aclp = (cm_aclent_t *) cm_data.aclBaseAddress;
+        memset(aclp, 0, size * sizeof(cm_aclent_t));
 
-    /* 
-     * Put all of these guys on the LRU queue 
-     */
-    for (i = 0; i < size; i++) {
-        osi_QAddH((osi_queue_t **) &cm_aclLRUp, (osi_queue_t **) &cm_aclLRUEndp, &aclp->q);
-        aclp++;
+        /* 
+         * Put all of these guys on the LRU queue 
+         */
+        for (i = 0; i < size; i++) {
+            aclp->magic = CM_ACLENT_MAGIC;
+            osi_QAddH((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q);
+            aclp++;
+        }
+    } else {
+        aclp = (cm_aclent_t *) cm_data.aclBaseAddress;
+        for (i = 0; i < size; i++) {
+            aclp->userp = NULL;
+            aclp->tgtLifetime = 0;
+            aclp++;
+        }
     }
     lock_ReleaseWrite(&cm_aclLock);
     return 0;
index f24ee67..23ea5e7 100644 (file)
 
 #define cm_TGTLifeTime(x)      (0x7fffffff)
 
+#define CM_ACLENT_MAGIC    ('A' | 'C' <<8 | 'L'<<16 | 'E'<<24)
+
 /*
  * Structure to hold an acl entry for a cached file
  */
 typedef struct cm_aclent {
     osi_queue_t q;             /* for quick removal from LRUQ */
+    afs_uint32 magic;           
     struct cm_aclent *nextp;   /* next guy same vnode */
     struct cm_scache *backp;   /* back ptr to vnode */
     struct cm_user *userp;     /* user whose access is cached */
@@ -28,7 +31,7 @@ typedef struct cm_aclent {
 
 extern osi_rwlock_t cm_aclLock;
 
-extern long cm_InitACLCache(long size);
+extern long cm_InitACLCache(int newFile, long size);
 
 extern long cm_FindACLCache(struct cm_scache *scp, struct cm_user *userp, long *rightsp);
 
@@ -40,4 +43,8 @@ extern void cm_FreeAllACLEnts(struct cm_scache *scp);
 
 extern void cm_InvalidateACLUser(struct cm_scache *scp, struct cm_user *userp);
 
+extern long cm_ValidateACLCache(void);
+
+extern long cm_ShutdownACLCache(void);
+
 #endif  /* _CM_ACLENT_H_ */
index 26ff242..151bccc 100644 (file)
 #include <windows.h>
 #endif
 #include <osi.h>
-#include <malloc.h>
 #include <stdio.h>
 #include <assert.h>
 #include <strsafe.h>
 
 #include "afsd.h"
+#include "cm_memmap.h"
 
 #ifdef DEBUG
 #define TRACE_BUFFER 1
@@ -64,49 +64,19 @@ osi_rwlock_t buf_globalLock;
  * to put stuff in buf_freeListp, and maintain the end
  * pointer manually
  */
-cm_buf_t *buf_freeListp;
-cm_buf_t *buf_freeListEndp;
 
 /* a pointer to a list of all buffers, just so that we can find them
  * easily for debugging, and for the incr syncer.  Locked under
  * the global lock.
  */
-cm_buf_t *buf_allp;
 
 /* defaults setup; these variables may be manually assigned into
  * before calling cm_Init, as a way of changing these defaults.
  */
-long buf_nbuffers = CM_BUF_BUFFERS;
-long buf_nOrigBuffers;
-long buf_bufferSize = CM_BUF_SIZE;
-long buf_hashSize = CM_BUF_HASHSIZE;
-int buf_cacheType = CM_BUF_CACHETYPE_FILE;
-
-#ifndef DJGPP
-static
-HANDLE CacheHandle;
-
-static 
-VOID * ViewOfFile;
-
-static
-SYSTEM_INFO sysInfo;
-#endif /* !DJGPP */
-
-/* buffer reservation variables */
-long buf_reservedBufs;
-long buf_maxReservedBufs;
-int buf_reserveWaiting;
 
 /* callouts for reading and writing data, etc */
 cm_buf_ops_t *cm_buf_opsp;
 
-/* pointer to hash table; size computed dynamically */
-cm_buf_t **buf_hashTablepp;
-
-/* another hash table */
-cm_buf_t **buf_fileHashTablepp;
-
 #ifdef DISKCACHE95
 /* for experimental disk caching support in Win95 client */
 cm_buf_t *buf_diskFreeListp;
@@ -115,9 +85,13 @@ cm_buf_t *buf_diskAllp;
 extern int cm_diskCacheEnabled;
 #endif /* DISKCACHE95 */
 
+/* set this to 1 when we are terminating to prevent access attempts */
+static int buf_ShutdownFlag = 0;
+
 /* hold a reference to an already held buffer */
 void buf_Hold(cm_buf_t *bp)
 {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
     lock_ObtainWrite(&buf_globalLock);
     bp->refCount++;
     lock_ReleaseWrite(&buf_globalLock);
@@ -132,20 +106,23 @@ void buf_IncrSyncer(long parm)
     cm_req_t req;
 
     lock_ObtainWrite(&buf_globalLock);
-    bp = buf_allp;
+    bp = cm_data.buf_allp;
     bp->refCount++;
     lock_ReleaseWrite(&buf_globalLock);
-    nAtOnce = buf_nbuffers / 10;
-    while (1) {
+    nAtOnce = cm_data.buf_nbuffers / 10;
+    while (buf_ShutdownFlag == 0) {
 #ifndef DJGPP
         i = SleepEx(5000, 1);
         if (i != 0) continue;
 #else
         thrd_Sleep(5000);
 #endif /* DJGPP */
-                
+            
+        if (buf_ShutdownFlag == 1)
+            return;
+
         /* now go through our percentage of the buffers */
-        for(i=0; i<nAtOnce; i++) {
+        for (i=0; i<nAtOnce; i++) {
             /* don't want its identity changing while we're
              * messing with it, so must do all of this with
              * bp held.
@@ -165,101 +142,108 @@ void buf_IncrSyncer(long parm)
             lock_ObtainWrite(&buf_globalLock);
             buf_LockedRelease(bp);
             bp = bp->allp;
-            if (!bp) bp = buf_allp;
+            if (!bp) 
+                bp = cm_data.buf_allp;
             bp->refCount++;
             lock_ReleaseWrite(&buf_globalLock);
         }      /* for loop over a bunch of buffers */
     }          /* whole daemon's while loop */
 }
 
-#ifndef DJGPP
-/* Create a security attribute structure suitable for use when the cache file
- * is created.  What we mainly want is that only the administrator should be
- * able to do anything with the file.  We create an ACL with only one entry,
- * an entry that grants all rights to the administrator.
- */
-PSECURITY_ATTRIBUTES CreateCacheFileSA()
+long
+buf_ValidateBuffers(void)
 {
-    PSECURITY_ATTRIBUTES psa;
-    PSECURITY_DESCRIPTOR psd;
-    SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
-    PSID AdminSID;
-    DWORD AdminSIDlength;
-    PACL AdminOnlyACL;
-    DWORD ACLlength;
-
-    /* Get Administrator SID */
-    AllocateAndInitializeSid(&authority, 2,
-                              SECURITY_BUILTIN_DOMAIN_RID,
-                              DOMAIN_ALIAS_RID_ADMINS,
-                              0, 0, 0, 0, 0, 0,
-                              &AdminSID);
-
-    /* Create Administrator-only ACL */
-    AdminSIDlength = GetLengthSid(AdminSID);
-    ACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
-        + AdminSIDlength - sizeof(DWORD);
-    AdminOnlyACL = GlobalAlloc(GMEM_FIXED, ACLlength);
-    InitializeAcl(AdminOnlyACL, ACLlength, ACL_REVISION);
-    AddAccessAllowedAce(AdminOnlyACL, ACL_REVISION,
-                         STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
-                         AdminSID);
-
-    /* Create security descriptor */
-    psd = GlobalAlloc(GMEM_FIXED, sizeof(SECURITY_DESCRIPTOR));
-    InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
-    SetSecurityDescriptorDacl(psd, TRUE, AdminOnlyACL, FALSE);
-
-    /* Create security attributes structure */
-    psa = GlobalAlloc(GMEM_FIXED, sizeof(SECURITY_ATTRIBUTES));
-    psa->nLength = sizeof(SECURITY_ATTRIBUTES);
-    psa->lpSecurityDescriptor = psd;
-    psa->bInheritHandle = TRUE;
-
-    return psa;
-}       
-#endif /* !DJGPP */
+    cm_buf_t * bp, *bpf, *bpa, *bpb;
+    afs_uint32 countb = 0, countf = 0, counta = 0;
+
+    for (bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) { 
+        if (bp->magic != CM_BUF_MAGIC) {
+            afsi_log("cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC");
+            fprintf(stderr, "cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC\n");
+            return -1;                  
+        }
+        countb++;                                                                
+        bpb = bp;     
 
-#ifndef DJGPP
-/* Free a security attribute structure created by CreateCacheFileSA() */
-VOID FreeCacheFileSA(PSECURITY_ATTRIBUTES psa)
-{
-    BOOL b1, b2;
-    PACL pAcl;
+        if (countb > cm_data.buf_nbuffers) {
+            afsi_log("cm_ValidateBuffers failure: countb > cm_data.buf_nbuffers");
+            fprintf(stderr, "cm_ValidateBuffers failure: countb > cm_data.buf_nbuffers\n");
+            return -6;                  
+        }
+    }
+
+    for (bp = cm_data.buf_freeListp; bp; bp=(cm_buf_t *) osi_QNext(&bp->q)) { 
+        if (bp->magic != CM_BUF_MAGIC) {
+            afsi_log("cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC");
+            fprintf(stderr, "cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC\n");
+            return -2;                  
+        }
+        countf++;                                                             
+        bpf = bp;    
+
+        if (countf > cm_data.buf_nbuffers) {
+            afsi_log("cm_ValidateBuffers failure: countf > cm_data.buf_nbuffers");
+            fprintf(stderr, "cm_ValidateBuffers failure: countf > cm_data.buf_nbuffers\n");
+            return -7;
+        }
+    }                                                                         
+                                                                              
+    for (bp = cm_data.buf_allp; bp; bp=bp->allp) {                            
+        if (bp->magic != CM_BUF_MAGIC) {
+            afsi_log("cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC");
+            fprintf(stderr, "cm_ValidateBuffers failure: bp->magic != CM_BUF_MAGIC\n");
+            return -3;                  
+        }
+        counta++;                                                             
+        bpa = bp;                                                             
+
+        if (counta > cm_data.buf_nbuffers) {
+            afsi_log("cm_ValidateBuffers failure: counta > cm_data.buf_nbuffers");
+            fprintf(stderr, "cm_ValidateBuffers failure: counta > cm_data.buf_nbuffers\n");
+            return -8;                  
+        }
+    }                                                                         
+                                                                              
+    if (countb != countf) {
+        afsi_log("cm_ValidateBuffers failure: countb != countf");
+        fprintf(stderr, "cm_ValidateBuffers failure: countb != countf\n");
+        return -4;         
+    }
+                                                                              
+    if (counta != cm_data.buf_nbuffers) {
+        afsi_log("cm_ValidateBuffers failure: counta != cm_data.buf_nbuffers");
+        fprintf(stderr, "cm_ValidateBuffers failure: counta != cm_data.buf_nbuffers\n");
+        return -5;                      
+    }
+                                                                              
+    return 0;                                                                 
+}
+
+void buf_Shutdown(void)  
+{                        
+    buf_ShutdownFlag = 1;
+}                        
 
-    GetSecurityDescriptorDacl(psa->lpSecurityDescriptor, &b1, &pAcl, &b2);
-    GlobalFree(pAcl);
-    GlobalFree(psa->lpSecurityDescriptor);
-    GlobalFree(psa);
-}       
-#endif /* !DJGPP */
-       
 /* initialize the buffer package; called with no locks
  * held during the initialization phase.
  */
-long buf_Init(cm_buf_ops_t *opsp)
+long buf_Init(int newFile, cm_buf_ops_t *opsp, long nbuffers)
 {
     static osi_once_t once;
     cm_buf_t *bp;
-    long sectorSize;
     thread_t phandle;
-#ifndef DJGPP
-    HANDLE hf, hm;
-    PSECURITY_ATTRIBUTES psa;
-#endif /* !DJGPP */
     long i;
     unsigned long pid;
     char *data;
-    long cs;
 
-#ifndef DJGPP
-    /* Get system info; all we really want is the allocation granularity */ 
-    GetSystemInfo(&sysInfo);
-#endif /* !DJGPP */
+    if ( newFile ) {
+        if (nbuffers) 
+            cm_data.buf_nbuffers = nbuffers;
 
-    /* Have to be able to reserve a whole chunk */
-    if (((buf_nbuffers - 3) * buf_bufferSize) < cm_chunkSize)
-        return CM_ERROR_TOOFEWBUFS;
+        /* Have to be able to reserve a whole chunk */
+        if (((cm_data.buf_nbuffers - 3) * cm_data.buf_blockSize) < cm_chunkSize)
+            return CM_ERROR_TOOFEWBUFS;
+    }
 
     /* recall for callouts */
     cm_buf_opsp = opsp;
@@ -268,135 +252,70 @@ long buf_Init(cm_buf_ops_t *opsp)
         /* initialize global locks */
         lock_InitializeRWLock(&buf_globalLock, "Global buffer lock");
 
-#ifndef DJGPP
-        /*
-        * Cache file mapping constrained by
-         * system allocation granularity;
-         * round up, assuming granularity is a power of two
-         */
-        cs = buf_nbuffers * buf_bufferSize;
-        cs = (cs + (sysInfo.dwAllocationGranularity - 1))
-            & ~(sysInfo.dwAllocationGranularity - 1);
-        if (cs != buf_nbuffers * buf_bufferSize) {
-            buf_nbuffers = cs / buf_bufferSize;
-            afsi_log("Cache size rounded up to %d buffers",
-                      buf_nbuffers);
-        }
-#endif /* !DJGPP */
-
-        /* remember this for those who want to reset it */
-        buf_nOrigBuffers = buf_nbuffers;
-
-        /* lower hash size to a prime number */
-        buf_hashSize = osi_PrimeLessThan(buf_hashSize);
-
-        /* create hash table */
-        buf_hashTablepp = malloc(buf_hashSize * sizeof(cm_buf_t *));
-        memset((void *)buf_hashTablepp, 0,
-                buf_hashSize * sizeof(cm_buf_t *));
-
-        /* another hash table */
-        buf_fileHashTablepp = malloc(buf_hashSize * sizeof(cm_buf_t *));
-        memset((void *)buf_fileHashTablepp, 0,
-                buf_hashSize * sizeof(cm_buf_t *));
+        if ( newFile ) {
+            /* remember this for those who want to reset it */
+            cm_data.buf_nOrigBuffers = cm_data.buf_nbuffers;
+            /* lower hash size to a prime number */
+            cm_data.buf_hashSize = osi_PrimeLessThan(CM_BUF_HASHSIZE);
+            /* create hash table */
+            memset((void *)cm_data.buf_hashTablepp, 0, cm_data.buf_hashSize * sizeof(cm_buf_t *));
+            
+            /* another hash table */
+            memset((void *)cm_data.buf_fileHashTablepp, 0, cm_data.buf_hashSize * sizeof(cm_buf_t *));
+
+            /* create buffer headers and put in free list */
+            bp = cm_data.bufHeaderBaseAddress;
+            data = cm_data.bufDataBaseAddress;
+            cm_data.buf_allp = NULL;
+            
+            for (i=0; i<cm_data.buf_nbuffers; i++) {
+                osi_assert(bp >= cm_data.bufHeaderBaseAddress && bp < (cm_buf_t *)cm_data.bufDataBaseAddress);
+                osi_assert(data >= cm_data.bufDataBaseAddress && data < cm_data.bufEndOfData);
                 
-        /* min value for which this works */
-        sectorSize = 1;
-
-#ifndef DJGPP
-        if (buf_cacheType == CM_BUF_CACHETYPE_FILE) {
-            /* Reserve buffer space by mapping cache file */
-            psa = CreateCacheFileSA();
-            hf = CreateFile(cm_CachePath,
-                             GENERIC_READ | GENERIC_WRITE,
-                             FILE_SHARE_READ | FILE_SHARE_WRITE,
-                             psa,
-                             OPEN_ALWAYS,
-                             FILE_ATTRIBUTE_NORMAL,
-                             NULL);
-            FreeCacheFileSA(psa);
-            if (hf == INVALID_HANDLE_VALUE) {
-                afsi_log("Error creating cache file \"%s\" error %d", 
-                          cm_CachePath, GetLastError());
-                return CM_ERROR_INVAL;
-            } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
-                BY_HANDLE_FILE_INFORMATION fileInfo;
-
-                afsi_log("Cache File \"%s\" already exists", cm_CachePath);
-                if ( GetFileInformationByHandle(hf, &fileInfo) )
-                    afsi_log("Existing File Size: %08X:%08X",
-                              fileInfo.nFileSizeHigh,
-                              fileInfo.nFileSizeLow);
-            }
-        } else { /* buf_cacheType == CM_BUF_CACHETYPE_VIRTUAL */
-            hf = INVALID_HANDLE_VALUE;
-        }
-        afsi_log("File Mapping Size: %08X", buf_nbuffers * buf_bufferSize);
-
-        CacheHandle = hf;
-        hm = CreateFileMapping(hf,
-                                NULL,
-                                PAGE_READWRITE,
-                                0, buf_nbuffers * buf_bufferSize,
-                                NULL);
-        if (hm == NULL) {
-            if (GetLastError() == ERROR_DISK_FULL) {
-                afsi_log("Error creating cache file mapping: disk full");
-                return CM_ERROR_TOOMANYBUFS;
-            }
-            return CM_ERROR_INVAL;
-        }
-        ViewOfFile = MapViewOfFile(hm,
-                                   FILE_MAP_ALL_ACCESS,
-                                   0, 0,   
-                                   buf_nbuffers * buf_bufferSize);
-        if (ViewOfFile == NULL) {
-            afsi_log("Error mapping view of file: 0x%X", GetLastError());
-            if (hf != INVALID_HANDLE_VALUE)
-                CloseHandle(hf);
-            CloseHandle(hm);
-            return CM_ERROR_INVAL;
-        }
-        CloseHandle(hm);
-
-        data = ViewOfFile;
-#else   
-        /* djgpp doesn't support memory mapped files */
-        data = malloc(buf_nbuffers * buf_bufferSize);
-#endif /* !DJGPP */
-
-        /* create buffer headers and put in free list */
-        bp = malloc(buf_nbuffers * sizeof(cm_buf_t));
-        buf_allp = NULL;
-        for(i=0; i<buf_nbuffers; i++) {
-            /* allocate and zero some storage */
-            memset(bp, 0, sizeof(cm_buf_t));
-
-            /* thread on list of all buffers */
-            bp->allp = buf_allp;
-            buf_allp = bp;
-
-            osi_QAdd((osi_queue_t **)&buf_freeListp, &bp->q);
-            bp->flags |= CM_BUF_INLRU;
-            lock_InitializeMutex(&bp->mx, "Buffer mutex");
-
-            /* grab appropriate number of bytes from aligned zone */
-            bp->datap = data;
-
-            /* setup last buffer pointer */
-            if (i == 0)
-                buf_freeListEndp = bp;
-
-            /* next */
-            bp++;
-            data += buf_bufferSize;
+                /* allocate and zero some storage */
+                memset(bp, 0, sizeof(cm_buf_t));
+                bp->magic = CM_BUF_MAGIC;
+                /* thread on list of all buffers */
+                bp->allp = cm_data.buf_allp;
+                cm_data.buf_allp = bp;
+                
+                osi_QAdd((osi_queue_t **)&cm_data.buf_freeListp, &bp->q);
+                bp->flags |= CM_BUF_INLRU;
+                lock_InitializeMutex(&bp->mx, "Buffer mutex");
+                
+                /* grab appropriate number of bytes from aligned zone */
+                bp->datap = data;
+                
+                /* setup last buffer pointer */
+                if (i == 0)
+                    cm_data.buf_freeListEndp = bp;
+                    
+                /* next */
+                bp++;
+                data += cm_data.buf_blockSize;
+            }       
+            /* none reserved at first */
+            cm_data.buf_reservedBufs = 0;
+            /* just for safety's sake */
+            cm_data.buf_maxReservedBufs = cm_data.buf_nbuffers - 3;
+        } else {
+            bp = cm_data.bufHeaderBaseAddress;
+            data = cm_data.bufDataBaseAddress;
+            
+            for (i=0; i<cm_data.buf_nbuffers; i++) {
+                lock_InitializeMutex(&bp->mx, "Buffer mutex");
+                bp->userp = NULL;
+                bp++;
+            }       
         }
-
-        /* none reserved at first */
-        buf_reservedBufs = 0;
-
-        /* just for safety's sake */
-        buf_maxReservedBufs = buf_nbuffers - 3;
+#ifdef TESTING
+        buf_ValidateBufQueues();
+#endif /* TESTING */
 
 #ifdef TRACE_BUFFER
         /* init the buffer trace log */
@@ -417,82 +336,42 @@ long buf_Init(cm_buf_ops_t *opsp)
 #endif /* !DJGPP */
     }
 
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
     return 0;
 }
 
-void
-buf_Shutdown(void)
-{
-    UnmapViewOfFile(ViewOfFile);
-    CloseHandle(CacheHandle);
-}
-
 /* add nbuffers to the buffer pool, if possible.
  * Called with no locks held.
  */
 long buf_AddBuffers(long nbuffers)
 {
-    cm_buf_t *bp;
-    int i;
-    char *data;
 #ifndef DJGPP
-    HANDLE hm;
-    long cs;
-
-    afsi_log("%d buffers being added to the existing cache of size %d",
-              nbuffers, buf_nbuffers);
-
-    if (buf_cacheType == CM_BUF_CACHETYPE_VIRTUAL) {
-        /* The size of a virtual cache cannot be changed after it has
-         * been created.  Subsequent calls to MapViewofFile() with
-         * an existing mapping object name would not allow the 
-         * object to be resized.  Return failure immediately.
-        */
-        return CM_ERROR_INVAL;
-    }
-
-    /*
-     * Cache file mapping constrained by
-     * system allocation granularity;
-     * round up, assuming granularity is a power of two;
-     * assume existing cache size is already rounded
+    /* The size of a virtual cache cannot be changed after it has
+     * been created.  Subsequent calls to MapViewofFile() with
+     * an existing mapping object name would not allow the 
+     * object to be resized.  Return failure immediately.
+     *
+     * A similar problem now occurs with the persistent cache
+     * given that the memory mapped file now contains a complex
+     * data structure.
      */
-    cs = nbuffers * buf_bufferSize;
-    cs = (cs + (sysInfo.dwAllocationGranularity - 1))
-        & ~(sysInfo.dwAllocationGranularity - 1);
-    if (cs != nbuffers * buf_bufferSize) {
-        nbuffers = cs / buf_bufferSize;
-    }
+    afsi_log("request to add %d buffers to the existing cache of size %d denied",
+              nbuffers, cm_data.buf_nbuffers);
 
-    /* Reserve additional buffer space by remapping cache file */
-    hm = CreateFileMapping(CacheHandle,
-                            NULL,
-                            PAGE_READWRITE,
-                            0, (buf_nbuffers + nbuffers) * buf_bufferSize,
-                            NULL);
-    if (hm == NULL) {
-        if (GetLastError() == ERROR_DISK_FULL)
-            return CM_ERROR_TOOMANYBUFS;
-        else
-            return CM_ERROR_INVAL;
-    }
-    data = MapViewOfFile(hm,
-                          FILE_MAP_ALL_ACCESS,
-                          0, buf_nbuffers * buf_bufferSize,
-                          nbuffers * buf_bufferSize);
-    if (data == NULL) {
-        CloseHandle(hm);
-        return CM_ERROR_INVAL;
-    }
-    CloseHandle(hm);
+    return CM_ERROR_INVAL;
 #else
-    data = malloc(buf_nbuffers * buf_bufferSize);
-#endif /* DJGPP */
+    cm_buf_t *bp;
+    int i;
+    char *data;
+
+    data = malloc(buf_nbuffers * cm_data.buf_blockSize);
 
     /* Create buffer headers and put in free list */
     bp = malloc(nbuffers * sizeof(*bp));
 
-    for(i=0; i<nbuffers; i++) {
+    for (i=0; i<nbuffers; i++) {
         memset(bp, 0, sizeof(*bp));
         
         lock_InitializeMutex(&bp->mx, "cm_buf_t");
@@ -504,19 +383,21 @@ long buf_AddBuffers(long nbuffers)
 
         lock_ObtainWrite(&buf_globalLock);
         /* note that buf_allp chain is covered by buf_globalLock now */
-        bp->allp = buf_allp;
-        buf_allp = bp;
-        osi_QAdd((osi_queue_t **) &buf_freeListp, &bp->q);
-        if (!buf_freeListEndp) buf_freeListEndp = bp;
-        buf_nbuffers++;
+        bp->allp = cm_data.buf_allp;
+        cm_data.buf_allp = bp;
+        osi_QAdd((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
+        if (!cm_data.buf_freeListEndp) 
+            cm_data.buf_freeListEndp = bp;
+        cm_data.buf_nbuffers++;
         lock_ReleaseWrite(&buf_globalLock);
 
         bp++;
-        data += buf_bufferSize;
+        data += cm_data.buf_blockSize;
        
     }   /* for loop over all buffers */
 
     return 0;
+#endif /* DJGPP */
 }       
 
 /* interface to set the number of buffers to an exact figure.
@@ -526,10 +407,10 @@ long buf_SetNBuffers(long nbuffers)
 {
     if (nbuffers < 10) 
         return CM_ERROR_INVAL;
-    if (nbuffers == buf_nbuffers) 
+    if (nbuffers == cm_data.buf_nbuffers) 
         return 0;
-    else if (nbuffers > buf_nbuffers)
-        return buf_AddBuffers(nbuffers - buf_nbuffers);
+    else if (nbuffers > cm_data.buf_nbuffers)
+        return buf_AddBuffers(nbuffers - cm_data.buf_nbuffers);
     else 
         return CM_ERROR_INVAL;
 }
@@ -547,6 +428,8 @@ void buf_Release(cm_buf_t *bp)
  */
 void buf_WaitIO(cm_buf_t *bp)
 {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
+
     while (1) {
         /* if no IO is happening, we're done */
         if (!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING)))
@@ -582,11 +465,11 @@ void buf_LockedRelease(cm_buf_t *bp)
     osi_assert(bp->refCount > 0);
     if (--bp->refCount == 0) {
         if (!(bp->flags & CM_BUF_INLRU)) {
-            osi_QAdd((osi_queue_t **) &buf_freeListp, &bp->q);
+            osi_QAdd((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
 
             /* watch for transition from empty to one element */
-            if (!buf_freeListEndp)
-                buf_freeListEndp = buf_freeListp;
+            if (!cm_data.buf_freeListEndp)
+                cm_data.buf_freeListEndp = cm_data.buf_freeListp;
             bp->flags |= CM_BUF_INLRU;
         }
     }
@@ -601,7 +484,7 @@ cm_buf_t *buf_LockedFind(struct cm_scache *scp, osi_hyper_t *offsetp)
     cm_buf_t *bp;
 
     i = BUF_HASH(&scp->fid, offsetp);
-    for(bp = buf_hashTablepp[i]; bp; bp=bp->hashp) {
+    for(bp = cm_data.buf_hashTablepp[i]; bp; bp=bp->hashp) {
         if (cm_FidCmp(&scp->fid, &bp->fid) == 0
              && offsetp->LowPart == bp->offset.LowPart
              && offsetp->HighPart == bp->offset.HighPart) {
@@ -637,14 +520,15 @@ cm_buf_t *buf_Find(struct cm_scache *scp, osi_hyper_t *offsetp)
  */
 void buf_LockedCleanAsync(cm_buf_t *bp, cm_req_t *reqp)
 {
-    long code;
+    long code = 0;
 
-    code = 0;
-    while ((bp->flags & (CM_BUF_WRITING | CM_BUF_DIRTY)) == CM_BUF_DIRTY) {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
+
+    while ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
         lock_ReleaseMutex(&bp->mx);
 
         code = (*cm_buf_opsp->Writep)(&bp->fid, &bp->offset,
-                                       buf_bufferSize, 0, bp->userp,
+                                       cm_data.buf_blockSize, 0, bp->userp,
                                        reqp);
                 
         lock_ObtainMutex(&bp->mx);
@@ -654,7 +538,7 @@ void buf_LockedCleanAsync(cm_buf_t *bp, cm_req_t *reqp)
 #ifdef DISKCACHE95
         /* Disk cache support */
         /* write buffer to disk cache (synchronous for now) */
-        diskcache_Update(bp->dcp, bp->datap, buf_bufferSize, bp->dataVersion);
+        diskcache_Update(bp->dcp, bp->datap, cm_data.buf_blockSize, bp->dataVersion);
 #endif /* DISKCACHE95 */
     };
 
@@ -682,6 +566,8 @@ void buf_Recycle(cm_buf_t *bp)
     cm_buf_t *tbp;
     cm_buf_t *prevBp, *nextBp;
 
+    osi_assert(bp->magic == CM_BUF_MAGIC);
+
     /* if we get here, we know that the buffer still has a 0 ref count,
      * and that it is clean and has no currently pending I/O.  This is
      * the dude to return.
@@ -700,7 +586,7 @@ void buf_Recycle(cm_buf_t *bp)
         /* Remove from hash */
 
         i = BUF_HASH(&bp->fid, &bp->offset);
-        lbpp = &(buf_hashTablepp[i]);
+        lbpp = &(cm_data.buf_hashTablepp[i]);
         for(tbp = *lbpp; tbp; lbpp = &tbp->hashp, tbp = *lbpp) {
             if (tbp == bp) break;
         }
@@ -718,7 +604,7 @@ void buf_Recycle(cm_buf_t *bp)
         if (prevBp)
             prevBp->fileHashp = nextBp;
         else
-            buf_fileHashTablepp[i] = nextBp;
+            cm_data.buf_fileHashTablepp[i] = nextBp;
         if (nextBp)
             nextBp->fileHashBackp = prevBp;
 
@@ -732,7 +618,7 @@ void buf_Recycle(cm_buf_t *bp)
     bp->idCounter++;
 
     /* make the fid unrecognizable */
-    memset(&bp->fid, 0, sizeof(bp->fid));
+    memset(&bp->fid, 0, sizeof(cm_fid_t));
 }       
 
 /* recycle a buffer, removing it from the free list, hashing in its new identity
@@ -755,6 +641,10 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
 
     cm_InitReq(&req);  /* just in case */
 
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
+
     while(1) {
       retry:
         lock_ObtainWrite(&buf_globalLock);
@@ -772,14 +662,14 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
          * instead of this; or better, we should have a transaction
          * throttler prevent us from entering this situation.
          */
-        osi_assertx(buf_freeListEndp != NULL, "buf_GetNewLocked: no free buffers");
+        osi_assertx(cm_data.buf_freeListEndp != NULL, "buf_GetNewLocked: no free buffers");
 
         /* look at all buffers in free list, some of which may temp.
          * have high refcounts and which then should be skipped,
          * starting cleaning I/O for those which are dirty.  If we find
          * a clean buffer, we rehash it, lock it and return it.
          */
-        for(bp = buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) {
+        for(bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) {
             /* check to see if it really has zero ref count.  This
              * code can bump refcounts, at least, so it may not be
              * zero.
@@ -853,15 +743,15 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
                 bp->fid = scp->fid;
                 bp->offset = *offsetp;
                 i = BUF_HASH(&scp->fid, offsetp);
-                bp->hashp = buf_hashTablepp[i];
-                buf_hashTablepp[i] = bp;
+                bp->hashp = cm_data.buf_hashTablepp[i];
+                cm_data.buf_hashTablepp[i] = bp;
                 i = BUF_FILEHASH(&scp->fid);
-                nextBp = buf_fileHashTablepp[i];
+                nextBp = cm_data.buf_fileHashTablepp[i];
                 bp->fileHashp = nextBp;
                 bp->fileHashBackp = NULL;
                 if (nextBp)
                     nextBp->fileHashBackp = bp;
-                buf_fileHashTablepp[i] = bp;
+                cm_data.buf_fileHashTablepp[i] = bp;
             }
 
             /* prepare to return it.  Start by giving it a good
@@ -875,11 +765,11 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
              */
             osi_assertx(bp->flags & CM_BUF_INLRU,
                          "buf_GetNewLocked: LRU screwup");
-            if (buf_freeListEndp == bp) {
+            if (cm_data.buf_freeListEndp == bp) {
                 /* we're the last guy in this queue, so maintain it */
-                buf_freeListEndp = (cm_buf_t *) osi_QPrev(&bp->q);
+                cm_data.buf_freeListEndp = (cm_buf_t *) osi_QPrev(&bp->q);
             }
-            osi_QRemove((osi_queue_t **) &buf_freeListp, &bp->q);
+            osi_QRemove((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
             bp->flags &= ~CM_BUF_INLRU;
 
             /* finally, grab the mutex so that people don't use it
@@ -891,6 +781,10 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
 
             lock_ReleaseWrite(&buf_globalLock);
             *bufpp = bp;
+
+#ifdef TESTING
+            buf_ValidateBufQueues();
+#endif /* TESTING */
             return 0;
         } /* for all buffers in lru queue */
         lock_ReleaseWrite(&buf_globalLock);
@@ -910,7 +804,7 @@ long buf_GetNew(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
 
     created = 0;
     pageOffset.HighPart = offsetp->HighPart;
-    pageOffset.LowPart = offsetp->LowPart & ~(buf_bufferSize-1);
+    pageOffset.LowPart = offsetp->LowPart & ~(cm_data.buf_blockSize-1);
     while (1) {
         lock_ObtainWrite(&buf_globalLock);
         bp = buf_LockedFind(scp, &pageOffset);
@@ -961,14 +855,20 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
     osi_hyper_t pageOffset;
     unsigned long tcount;
     int created;
+    long lcount = 0;
 #ifdef DISKCACHE95
     cm_diskcache_t *dcp;
 #endif /* DISKCACHE95 */
 
     created = 0;
     pageOffset.HighPart = offsetp->HighPart;
-    pageOffset.LowPart = offsetp->LowPart & ~(buf_bufferSize-1);
+    pageOffset.LowPart = offsetp->LowPart & ~(cm_data.buf_blockSize-1);
     while (1) {
+        lcount++;
+#ifdef TESTING
+        buf_ValidateBufQueues();
+#endif /* TESTING */
+
         lock_ObtainWrite(&buf_globalLock);
         bp = buf_LockedFind(scp, &pageOffset);
         lock_ReleaseWrite(&buf_globalLock);
@@ -993,8 +893,12 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
             continue;
 
         /* something else went wrong */
-        if (code != 0) 
+        if (code != 0) { 
+#ifdef TESTING
+            buf_ValidateBufQueues();
+#endif /* TESTING */
             return code;
+        }
                 
         /* otherwise, we have a locked buffer that we just created */
         created = 1;
@@ -1016,10 +920,10 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
 
         /* start the I/O; may drop lock */
         bp->flags |= CM_BUF_READING;
-        code = (*cm_buf_opsp->Readp)(bp, buf_bufferSize, &tcount, NULL);
+        code = (*cm_buf_opsp->Readp)(bp, cm_data.buf_blockSize, &tcount, NULL);
 
 #ifdef DISKCACHE95
-        code = diskcache_Get(&bp->fid, &bp->offset, bp->datap, buf_bufferSize, &bp->dataVersion, &tcount, &dcp);
+        code = diskcache_Get(&bp->fid, &bp->offset, bp->datap, cm_data.buf_blockSize, &bp->dataVersion, &tcount, &dcp);
         bp->dcp = dcp;    /* pointer to disk cache struct. */
 #endif /* DISKCACHE95 */
 
@@ -1037,6 +941,9 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
                 }
                 lock_ReleaseMutex(&bp->mx);
                 buf_Release(bp);
+#ifdef TESTING
+                buf_ValidateBufQueues();
+#endif /* TESTING */
                 return code;
 #ifndef DJGPP
             }
@@ -1045,8 +952,8 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
             /* otherwise, I/O completed instantly and we're done, except
              * for padding the xfr out with 0s and checking for EOF
              */
-            if (tcount < (unsigned long) buf_bufferSize) {
-                memset(bp->datap+tcount, 0, buf_bufferSize - tcount);
+            if (tcount < (unsigned long) cm_data.buf_blockSize) {
+                memset(bp->datap+tcount, 0, cm_data.buf_blockSize - tcount);
                 if (tcount == 0)
                     bp->flags |= CM_BUF_EOF;
             }
@@ -1076,15 +983,18 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
      */
     lock_ObtainWrite(&buf_globalLock);
     if (bp->flags & CM_BUF_INLRU) {
-        if (buf_freeListEndp == bp)
-            buf_freeListEndp = (cm_buf_t *) osi_QPrev(&bp->q);
-        osi_QRemove((osi_queue_t **) &buf_freeListp, &bp->q);
+        if (cm_data.buf_freeListEndp == bp)
+            cm_data.buf_freeListEndp = (cm_buf_t *) osi_QPrev(&bp->q);
+        osi_QRemove((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
         bp->flags &= ~CM_BUF_INLRU;
     }
     lock_ReleaseWrite(&buf_globalLock);
 
     osi_Log3(buf_logp, "buf_Get returning bp 0x%x for file 0x%x, offset 0x%x",
               bp, (long) scp, offsetp->LowPart);
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
     return 0;
 }
 
@@ -1100,7 +1010,7 @@ long buf_CountFreeList(void)
 
     count = 0;
     lock_ObtainRead(&buf_globalLock);
-    for(bufp = buf_freeListp; bufp; bufp = (cm_buf_t *) osi_QNext(&bufp->q)) {
+    for(bufp = cm_data.buf_freeListp; bufp; bufp = (cm_buf_t *) osi_QNext(&bufp->q)) {
         /* if the buffer doesn't have an identity, or if the buffer
          * has been invalidate (by having its DV stomped upon), then
          * count it as free, since it isn't really being utilized.
@@ -1115,6 +1025,8 @@ long buf_CountFreeList(void)
 /* clean a buffer synchronously */
 void buf_CleanAsync(cm_buf_t *bp, cm_req_t *reqp)
 {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
+
     lock_ObtainMutex(&bp->mx);
     buf_LockedCleanAsync(bp, reqp);
     lock_ReleaseMutex(&bp->mx);
@@ -1123,6 +1035,8 @@ void buf_CleanAsync(cm_buf_t *bp, cm_req_t *reqp)
 /* wait for a buffer's cleaning to finish */
 void buf_CleanWait(cm_buf_t *bp)
 {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
+
     lock_ObtainMutex(&bp->mx);
     if (bp->flags & CM_BUF_WRITING) {
         buf_WaitIO(bp);
@@ -1137,6 +1051,7 @@ void buf_CleanWait(cm_buf_t *bp)
  */
 void buf_SetDirty(cm_buf_t *bp)
 {
+    osi_assert(bp->magic == CM_BUF_MAGIC);
     osi_assert(bp->refCount > 0);
        
     osi_Log1(buf_logp, "buf_SetDirty 0x%x", bp);
@@ -1175,25 +1090,31 @@ long buf_CleanAndReset(void)
     cm_req_t req;
 
     lock_ObtainWrite(&buf_globalLock);
-    for(i=0; i<buf_hashSize; i++) {
-        for(bp = buf_hashTablepp[i]; bp; bp = bp->hashp) {
-            bp->refCount++;
-            lock_ReleaseWrite(&buf_globalLock);
+    for(i=0; i<cm_data.buf_hashSize; i++) {
+        for(bp = cm_data.buf_hashTablepp[i]; bp; bp = bp->hashp) {
+            if ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
+                bp->refCount++;
+                lock_ReleaseWrite(&buf_globalLock);
 
-            /* now no locks are held; clean buffer and go on */
-            cm_InitReq(&req);
-            buf_CleanAsync(bp, &req);
-            buf_CleanWait(bp);
+                /* now no locks are held; clean buffer and go on */
+                cm_InitReq(&req);
+                buf_CleanAsync(bp, &req);
+                buf_CleanWait(bp);
 
-            /* relock and release buffer */
-            lock_ObtainWrite(&buf_globalLock);
-            buf_LockedRelease(bp);
+                /* relock and release buffer */
+                lock_ObtainWrite(&buf_globalLock);
+                buf_LockedRelease(bp);
+            } /* dirty */
         } /* over one bucket */
     }  /* for loop over all hash buckets */
 
     /* release locks */
     lock_ReleaseWrite(&buf_globalLock);
 
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
+    
     /* and we're done */
     return 0;
 }       
@@ -1205,14 +1126,14 @@ void buf_ReserveBuffers(long nbuffers)
 {
     lock_ObtainWrite(&buf_globalLock);
     while (1) {
-        if (buf_reservedBufs + nbuffers > buf_maxReservedBufs) {
-            buf_reserveWaiting = 1;
+        if (cm_data.buf_reservedBufs + nbuffers > cm_data.buf_maxReservedBufs) {
+            cm_data.buf_reserveWaiting = 1;
             osi_Log1(buf_logp, "buf_ReserveBuffers waiting for %d bufs", nbuffers);
-            osi_SleepW((long) &buf_reservedBufs, &buf_globalLock);
+            osi_SleepW((long) &cm_data.buf_reservedBufs, &buf_globalLock);
             lock_ObtainWrite(&buf_globalLock);
         }
         else {
-            buf_reservedBufs += nbuffers;
+            cm_data.buf_reservedBufs += nbuffers;
             break;
         }
     }
@@ -1224,11 +1145,11 @@ int buf_TryReserveBuffers(long nbuffers)
     int code;
 
     lock_ObtainWrite(&buf_globalLock);
-    if (buf_reservedBufs + nbuffers > buf_maxReservedBufs) {
+    if (cm_data.buf_reservedBufs + nbuffers > cm_data.buf_maxReservedBufs) {
         code = 0;
     }
     else {
-        buf_reservedBufs += nbuffers;
+        cm_data.buf_reservedBufs += nbuffers;
         code = 1;
     }
     lock_ReleaseWrite(&buf_globalLock);
@@ -1241,10 +1162,10 @@ int buf_TryReserveBuffers(long nbuffers)
 void buf_UnreserveBuffers(long nbuffers)
 {
     lock_ObtainWrite(&buf_globalLock);
-    buf_reservedBufs -= nbuffers;
-    if (buf_reserveWaiting) {
-        buf_reserveWaiting = 0;
-        osi_Wakeup((long) &buf_reservedBufs);
+    cm_data.buf_reservedBufs -= nbuffers;
+    if (cm_data.buf_reserveWaiting) {
+        cm_data.buf_reserveWaiting = 0;
+        osi_Wakeup((long) &cm_data.buf_reservedBufs);
     }
     lock_ReleaseWrite(&buf_globalLock);
 }       
@@ -1271,7 +1192,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
     i = BUF_FILEHASH(&scp->fid);
 
     lock_ObtainWrite(&buf_globalLock);
-    bufp = buf_fileHashTablepp[i];
+    bufp = cm_data.buf_fileHashTablepp[i];
     if (bufp == NULL) {
         lock_ReleaseWrite(&buf_globalLock);
         return 0;
@@ -1284,7 +1205,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
         lock_ObtainMutex(&bufp->mx);
 
         bufEnd.HighPart = 0;
-        bufEnd.LowPart = buf_bufferSize;
+        bufEnd.LowPart = cm_data.buf_blockSize;
         bufEnd = LargeIntegerAdd(bufEnd, bufp->offset);
 
         if (cm_FidCmp(&bufp->fid, &scp->fid) == 0 &&
@@ -1330,10 +1251,10 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
                  * seek and write past EOF, and make this data
                  * visible again.
                  */
-                bufferPos = sizep->LowPart & (buf_bufferSize - 1);
+                bufferPos = sizep->LowPart & (cm_data.buf_blockSize - 1);
                 osi_assert(bufferPos != 0);
                 memset(bufp->datap + bufferPos, 0,
-                        buf_bufferSize - bufferPos);
+                        cm_data.buf_blockSize - bufferPos);
             }
 
             lock_ReleaseWrite(&buf_globalLock);
@@ -1356,10 +1277,19 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
              */
             if (nbufp) 
                 buf_Release(nbufp);
+
+#ifdef TESTING
+            buf_ValidateBufQueues();
+#endif /* TESTING */
+
             return code;
         }
     }
 
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
+
     /* success */
     return 0;
 }
@@ -1376,10 +1306,11 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 
     code = 0;
     lock_ObtainWrite(&buf_globalLock);
-    bp = buf_fileHashTablepp[i];
-    if (bp) bp->refCount++;
+    bp = cm_data.buf_fileHashTablepp[i];
+    if (bp) 
+        bp->refCount++;
     lock_ReleaseWrite(&buf_globalLock);
-    for(; bp; bp = nbp) {
+    for (; bp; bp = nbp) {
         didRelease = 0;        /* haven't released this buffer yet */
 
         /* clean buffer synchronously */
@@ -1392,7 +1323,8 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
             lock_ReleaseMutex(&bp->mx);
 
             code = (*cm_buf_opsp->Stabilizep)(scp, userp, reqp);
-            if (code) goto skip;
+            if (code) 
+                goto skip;
 
             lock_ObtainWrite(&buf_globalLock);
             /* actually, we only know that buffer is clean if ref
@@ -1402,7 +1334,8 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
                 if (bp->refCount == 1) {       /* bp is held above */
                     buf_LockedRelease(bp);
                     nbp = bp->fileHashp;
-                    if (nbp) nbp->refCount++;
+                    if (nbp) 
+                        nbp->refCount++;
                     didRelease = 1;
                     buf_Recycle(bp);
                 }
@@ -1415,12 +1348,17 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
       skip:
         if (!didRelease) {
             lock_ObtainWrite(&buf_globalLock);
-            if (nbp = bp->fileHashp) nbp->refCount++;
+            if (nbp = bp->fileHashp) 
+                nbp->refCount++;
             buf_LockedRelease(bp);
             lock_ReleaseWrite(&buf_globalLock);
         }
     }  /* for loop over a bunch of buffers */
 
+#ifdef TESTING
+            buf_ValidateBufQueues();
+#endif /* TESTING */
+
     /* done */
     return code;
 }       
@@ -1436,10 +1374,11 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
 
     code = 0;
     lock_ObtainWrite(&buf_globalLock);
-    bp = buf_fileHashTablepp[i];
-    if (bp) bp->refCount++;
+    bp = cm_data.buf_fileHashTablepp[i];
+    if (bp) 
+        bp->refCount++;
     lock_ReleaseWrite(&buf_globalLock);
-    for(; bp; bp = nbp) {
+    for (; bp; bp = nbp) {
         /* clean buffer synchronously */
         if (cm_FidCmp(&bp->fid, &scp->fid) == 0) {
             if (userp) {
@@ -1465,33 +1404,78 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
         lock_ObtainWrite(&buf_globalLock);
         buf_LockedRelease(bp);
         nbp = bp->fileHashp;
-        if (nbp) nbp->refCount++;
+        if (nbp) 
+            nbp->refCount++;
         lock_ReleaseWrite(&buf_globalLock);
     }  /* for loop over a bunch of buffers */
 
+#ifdef TESTING
+    buf_ValidateBufQueues();
+#endif /* TESTING */
+
     /* done */
     return code;
 }
 
+#ifdef TESTING
+void
+buf_ValidateBufQueues(void)
+{
+    cm_buf_t * bp, *bpb, *bpf, *bpa;
+    afs_uint32 countf=0, countb=0, counta=0;
+
+    lock_ObtainRead(&buf_globalLock);
+    for (bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) {
+        if (bp->magic != CM_BUF_MAGIC)
+            DebugBreak();
+        countb++;
+        bpb = bp;
+    }
+
+    for (bp = cm_data.buf_freeListp; bp; bp=(cm_buf_t *) osi_QNext(&bp->q)) {
+        if (bp->magic != CM_BUF_MAGIC)
+            DebugBreak();
+        countf++;
+        bpf = bp;
+    }
+
+    for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
+        if (bp->magic != CM_BUF_MAGIC)
+            DebugBreak();
+        counta++;
+        bpa = bp;
+    }
+    lock_ReleaseRead(&buf_globalLock);
+
+    if (countb != countf)
+        DebugBreak();
+
+    if (counta != cm_data.buf_nbuffers)
+        DebugBreak();  
+}
+#endif /* TESTING */
+
 /* dump the contents of the buf_hashTablepp. */
-int cm_DumpBufHashTable(FILE *outputFile, char *cookie)
+int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock)
 {
     int zilch;
     cm_buf_t *bp;
     char output[1024];
     int i;
   
-    if (buf_hashTablepp == NULL)
+    if (cm_data.buf_hashTablepp == NULL)
         return -1;
 
-    lock_ObtainRead(&buf_globalLock);
+    if (lock)
+        lock_ObtainRead(&buf_globalLock);
   
-    StringCbPrintfA(output, sizeof(output), "%s - dumping buf_HashTable - buf_hashSize=%d\n", cookie, buf_hashSize);
+    StringCbPrintfA(output, sizeof(output), "%s - dumping buf_HashTable - buf_hashSize=%d\n", 
+                    cookie, cm_data.buf_hashSize);
     WriteFile(outputFile, output, strlen(output), &zilch, NULL);
   
-    for (i = 0; i < buf_hashSize; i++)
+    for (i = 0; i < cm_data.buf_hashSize; i++)
     {
-        for (bp = buf_hashTablepp[i]; bp; bp=bp->hashp) 
+        for (bp = cm_data.buf_hashTablepp[i]; bp; bp=bp->hashp) 
         {
             if (bp->refCount)
             {
@@ -1506,7 +1490,8 @@ int cm_DumpBufHashTable(FILE *outputFile, char *cookie)
     StringCbPrintfA(output, sizeof(output), "%s - Done dumping buf_HashTable.\n", cookie);
     WriteFile(outputFile, output, strlen(output), &zilch, NULL);
 
-    lock_ReleaseRead(&buf_globalLock);
+    if (lock)
+        lock_ReleaseRead(&buf_globalLock);
     return 0;
 }
 
index c7f59fc..8174d0d 100644 (file)
 
 /* default # of buffers if not changed */
 #define CM_BUF_BUFFERS 100
-extern long buf_nbuffers;
-
-/* orig # of buffers */
-extern long buf_nOrigBuffers;
 
 /* default buffer size */
-#define CM_BUF_SIZE            4096
-extern long buf_bufferSize;
+#define CM_BUF_BLOCKSIZE CM_CONFIGDEFAULT_BLOCKSIZE
 
 /* default hash size */
 #define CM_BUF_HASHSIZE        1024
-extern long buf_hashSize;
 
 /* cache type */
 #define CM_BUF_CACHETYPE_FILE 1
@@ -40,28 +34,34 @@ extern int buf_cacheType;
 /* force it to be signed so that mod comes out positive or 0 */
 #define BUF_HASH(fidp,offsetp) ((((fidp)->vnode+((fidp)->unique << 5)  \
                                +(fidp)->volume+(fidp)->cell            \
-                               +((offsetp)->LowPart / buf_bufferSize)) \
+                               +((offsetp)->LowPart / cm_data.buf_blockSize))  \
                                  & 0x7fffffff)                         \
-                                  % buf_hashSize)
+                                  % cm_data.buf_hashSize)
 
 /* another hash fn */
 #define BUF_FILEHASH(fidp) ((((fidp)->vnode+((fidp)->unique << 5)      \
                                +(fidp)->volume+(fidp)->cell)           \
                                  & 0x7fffffff)                         \
-                                  % buf_hashSize)
+                                  % cm_data.buf_hashSize)
 
 /* backup over pointer to the buffer */
 #define BUF_OVERTOBUF(op) ((cm_buf_t *)(((char *)op) - ((long)(&((cm_buf_t *)0)->over))))
 
+#ifdef notdef
 /* pretend we have logs, too */
 typedef char cm_log_t;
+#endif
+
+#define CM_BUF_MAGIC    ('B' | 'U' <<8 | 'F'<<16 | 'F'<<24)
 
 /* represents a single buffer */
 typedef struct cm_buf {
-       osi_queue_t q;          /* queue of all zero-refcount buffers */
-       struct cm_buf *hashp;   /* hash bucket pointer */
-       struct cm_buf *fileHashp; /* file hash bucket pointer */
-       struct cm_buf *fileHashBackp;   /* file hash bucket back pointer */
+    osi_queue_t q;             /* queue of all zero-refcount buffers */
+    afs_uint32     magic;
+    struct cm_buf *allp;       /* next in all list */
+    struct cm_buf *hashp;      /* hash bucket pointer */
+    struct cm_buf *fileHashp;   /* file hash bucket pointer */
+    struct cm_buf *fileHashBackp;      /* file hash bucket back pointer */
                                /*
                                 * The file hash chain is doubly linked, since
                                 * these chains can get rather long.  The
@@ -70,31 +70,30 @@ typedef struct cm_buf {
                                 * hash function is good and if there are
                                 * enough buckets for the size of the cache.
                                 */
-        struct cm_buf *allp;   /* next in all list */
-       osi_mutex_t mx;         /* mutex protecting structure except refcount */
-    unsigned long refCount;            /* reference count (buf_globalLock) */
-        long idCounter;                /* counter for softrefs; bumped at each recycle */
-        long dirtyCounter;     /* bumped at each dirty->clean transition */
+    osi_mutex_t mx;            /* mutex protecting structure except refcount */
+    unsigned long refCount;    /* reference count (buf_globalLock) */
+    long idCounter;            /* counter for softrefs; bumped at each recycle */
+    long dirtyCounter;         /* bumped at each dirty->clean transition */
 #ifdef notdef
-       struct cm_log *logp;    /* log for this buffer, if any */
-       osi_hyper_t lsn;        /* lsn to force to (last LSN changing this buffer) */
+    cm_log_t *logp;            /* log for this buffer, if any */
+    osi_hyper_t lsn;           /* lsn to force to (last LSN changing this buffer) */
 #endif /* notdef */
-        osi_hyper_t offset;    /* offset */
-       cm_fid_t fid;           /* file ID */
-       long flags;             /* flags we're using */
-        long size;             /* size in bytes of this buffer */
-        char *datap;           /* data in this buffer */
-       unsigned long error;    /* last error code, if CM_BUF_ERROR is set */
-        struct cm_user *userp; /* user who wrote to the buffer last */
+    osi_hyper_t offset;                /* offset */
+    cm_fid_t fid;              /* file ID */
+    long flags;                        /* flags we're using */
+    long size;                 /* size in bytes of this buffer */
+    char *datap;               /* data in this buffer */
+    unsigned long error;       /* last error code, if CM_BUF_ERROR is set */
+    cm_user_t *userp;          /* user who wrote to the buffer last */
 #ifndef DJGPP
-        OVERLAPPED over;       /* overlapped structure for I/O */
+    OVERLAPPED over;           /* overlapped structure for I/O */
 #endif
         
-        /* fields added for the CM; locked by scp->mx */
-        long dataVersion;      /* data version of this page */
-        long cmFlags;          /* flags for cm */
+    /* fields added for the CM; locked by scp->mx */
+    long dataVersion;          /* data version of this page */
+    long cmFlags;              /* flags for cm */
 #ifdef DISKCACHE95
-        cm_diskcache_t *dcp;    /* diskcache structure */
+    cm_diskcache_t *dcp;        /* diskcache structure */
 #endif /* DISKCACHE95 */
 } cm_buf_t;
 
@@ -106,8 +105,8 @@ typedef struct cm_buf {
 
 /* represents soft reference which is OK to lose on a recycle */
 typedef struct cm_softRef {
-       cm_buf_t *bufp; /* buffer (may get reused) */
-        long counter;          /* counter of changes to identity */
+    cm_buf_t *bufp;    /* buffer (may get reused) */
+    long counter;              /* counter of changes to identity */
 } cm_softRef_t;
 
 #define CM_BUF_READING 1       /* now reading buffer to the disk */
@@ -121,26 +120,17 @@ typedef struct cm_softRef {
 #define CM_BUF_EOF             0x100   /* read 0 bytes; used for detecting EOF */
 
 typedef struct cm_buf_ops {
-       long (*Writep)(void *, osi_hyper_t *, long, long, struct cm_user *,
+    long (*Writep)(void *, osi_hyper_t *, long, long, struct cm_user *,
                        struct cm_req *);
-       long (*Readp)(cm_buf_t *, long, long *, struct cm_user *);
-        long (*Stabilizep)(void *, struct cm_user *, struct cm_req *);
-        long (*Unstabilizep)(void *, struct cm_user *);
+    long (*Readp)(cm_buf_t *, long, long *, struct cm_user *);
+    long (*Stabilizep)(void *, struct cm_user *, struct cm_req *);
+    long (*Unstabilizep)(void *, struct cm_user *);
 } cm_buf_ops_t;
 
 /* global locks */
 extern osi_rwlock_t buf_globalLock;
 
-/* buffer free list */
-extern cm_buf_t *buf_freeListp;
-
-/* pointer to hash table */
-extern cm_buf_t **buf_hashTablepp;
-
-/* another hash table */
-extern cm_buf_t **buf_fileHashTablepp;
-
-extern long buf_Init(cm_buf_ops_t *);
+extern long buf_Init(int newFile, cm_buf_ops_t *, long nbuffers);
 
 extern void buf_Shutdown(void);
 
@@ -184,6 +174,10 @@ extern int buf_TryReserveBuffers(long);
 
 extern void buf_UnreserveBuffers(long);
 
+#ifdef TESTING
+extern void buf_ValidateBufQueues(void);
+#endif /* TESTING */
+
 extern osi_log_t *buf_logp;
 
 extern long buf_Truncate(struct cm_scache *scp, cm_user_t *userp,
@@ -197,6 +191,8 @@ extern long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp,
 
 extern long buf_SetNBuffers(long nbuffers);
 
+extern long buf_ValidateBuffers(void);
+
 extern void buf_ForceTrace(BOOL flush);
 
 /* error codes */
index 917bf36..1108c16 100644 (file)
 #include <stdlib.h>
 
 #include <osi.h>
+#include <rx_pthread.h>
 
 #include "afsd.h"
+#include <WINNT/syscfg.h>
+#include <WINNT/afsreg.h>
 
 /*extern void afsi_log(char *pattern, ...);*/
 
@@ -75,7 +78,7 @@ void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
     lock_ObtainWrite(&cm_callbackLock);
 
     osi_Log3(afsd_logp, "RecordRacingRevoke Volume %d Flags %lX activeCalls %d",
-             fidp->volume, cancelFlags, cm_activeCallbackGrantingCalls);
+               fidp ? fidp->volume : 0, cancelFlags, cm_activeCallbackGrantingCalls);
 
     if (cm_activeCallbackGrantingCalls > 0) {
         rp = malloc(sizeof(*rp));
@@ -94,8 +97,30 @@ void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
  */
 void cm_CallbackNotifyChange(cm_scache_t *scp)
 {
-    osi_Log2(afsd_logp, "CallbackNotifyChange FileType %d Flags %lX",
-              scp->fileType, scp->flags);
+    DWORD dwDelay = 0;
+    HKEY  hKey;
+    DWORD dummyLen;
+
+    if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                      AFSREG_CLT_OPENAFS_SUBKEY,
+                      0,
+                      KEY_READ|KEY_QUERY_VALUE,
+                      &hKey) == ERROR_SUCCESS) {
+
+        dummyLen = sizeof(DWORD);
+        RegQueryValueEx(hKey, "CallBack Notify Change Delay", NULL, NULL,
+                        (BYTE *) &dwDelay, &dummyLen);
+        RegCloseKey(hKey);
+    }
+
+    if (dwDelay > 5000)    /* do not allow a delay of more then 5 seconds */
+        dwDelay = 5000;   
+
+    osi_Log3(afsd_logp, "CallbackNotifyChange FileType %d Flags %lX Delay %dms",
+              scp->fileType, scp->flags, dwDelay);
+
+    if (dwDelay)
+        Sleep(dwDelay);
 
     if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
         if (scp->flags & CM_SCACHEFLAG_ANYWATCH)
@@ -111,12 +136,13 @@ void cm_CallbackNotifyChange(cm_scache_t *scp)
         tfid.vnode = scp->parentVnode;
         tfid.unique = scp->parentUnique;
         dscp = cm_FindSCache(&tfid);
-        if (dscp &&
-             dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+        if ( dscp &&
+             dscp->flags & CM_SCACHEFLAG_ANYWATCH )
             smb_NotifyChange( 0,
                               FILE_NOTIFY_GENERIC_FILE_FILTER,
                               dscp,   NULL, NULL, TRUE);
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (dscp) 
+            cm_ReleaseSCache(dscp);
     }
 }
 
@@ -142,7 +168,7 @@ void cm_RevokeCallback(struct rx_call *callp, AFSFid *fidp)
     tfid.unique = fidp->Unique;
     hash = CM_SCACHE_HASH(&tfid);
 
-    osi_Log3(afsd_logp, "RevokeCallback vol %d vn %d un %d",
+    osi_Log3(afsd_logp, "RevokeCallback vol %u vn %u uniq %u",
              fidp->Volume, fidp->Vnode, fidp->Unique);
         
     /* do this first, so that if we're executing a callback granting call
@@ -156,13 +182,17 @@ void cm_RevokeCallback(struct rx_call *callp, AFSFid *fidp)
     /* do all in the hash bucket, since we don't know how many we'll find with
      * varying cells.
      */
-    for (scp = cm_hashTablep[hash]; scp; scp=scp->nextp) {
+    for (scp = cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
         if (scp->fid.volume == tfid.volume &&
              scp->fid.vnode == tfid.vnode &&
-             scp->fid.unique == tfid.unique) {
+             scp->fid.unique == tfid.unique &&
+             scp->cbExpires > 0 && 
+             scp->cbServerp != NULL)
+        {
             cm_HoldSCacheNoLock(scp);
             lock_ReleaseWrite(&cm_scacheLock);
-            osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
+            osi_Log4(afsd_logp, "RevokeCallback Discarding SCache scp 0x%x vol %u vn %u uniq %u", 
+                     scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
             lock_ObtainMutex(&scp->mx);
             cm_DiscardSCache(scp);
             lock_ReleaseMutex(&scp->mx);
@@ -172,6 +202,9 @@ void cm_RevokeCallback(struct rx_call *callp, AFSFid *fidp)
         }
     }
     lock_ReleaseWrite(&cm_scacheLock);
+
+    osi_Log3(afsd_logp, "RevokeCallback Complete vol %u vn %u uniq %u",
+             fidp->Volume, fidp->Vnode, fidp->Unique);
 }
 
 /* called to revoke a volume callback, which is typically issued when a volume
@@ -185,7 +218,7 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
     cm_scache_t *scp;
     cm_fid_t tfid;
 
-    osi_Log1(afsd_logp, "RevokeVolumeCallback %d", fidp->Volume);
+    osi_Log1(afsd_logp, "RevokeVolumeCallback vol %d", fidp->Volume);
 
     /* do this first, so that if we're executing a callback granting call
      * at this moment, we kill it before it can be merged in.  Otherwise,
@@ -198,13 +231,16 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
 
 
     lock_ObtainWrite(&cm_scacheLock);
-    for (hash = 0; hash < cm_hashTableSize; hash++) {
-        for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
-            if (scp->fid.volume == fidp->Volume) {
+    for (hash = 0; hash < cm_data.hashTableSize; hash++) {
+        for(scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
+            if (scp->fid.volume == fidp->Volume &&
+                 scp->cbExpires > 0 &&
+                 scp->cbServerp != NULL) {
                 cm_HoldSCacheNoLock(scp);
                 lock_ReleaseWrite(&cm_scacheLock);
                 lock_ObtainMutex(&scp->mx);
-                osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
+                osi_Log4(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%x vol %u vn %u uniq %u", 
+                          scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
                 cm_DiscardSCache(scp);
                 lock_ReleaseMutex(&scp->mx);
                 cm_CallbackNotifyChange(scp);
@@ -215,17 +251,96 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
     }  /* search all hash buckets */
 
     lock_ReleaseWrite(&cm_scacheLock);
+
+    osi_Log1(afsd_logp, "RevokeVolumeCallback Complete vol %d", fidp->Volume);
 }
 
+/*
+ * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
+ * given data pointer, without triggering "cast truncates pointer"
+ * warnings.  We use this where we explicitly don't care whether a
+ * pointer is truncated -- it loses information where a pointer is
+ * larger than an afs_int32.
+ */
+
+static afs_int32
+afs_data_pointer_to_int32(const void *p)
+{
+    union {
+        afs_int32 i32[sizeof(void *) / sizeof(afs_int32)];
+        const void *p;
+    } ip;
+
+    int i32_sub;                /* subscript of least significant afs_int32 in ip.i32[] */
+
+    /* set i32_sub */
+
+    {
+        /* used to determine the byte order of the system */
+
+        union {
+            char c[sizeof(int) / sizeof(char)];
+            int i;
+        } ci;
+
+        ci.i = 1;
+        if (ci.c[0] == 1) {
+            /* little-endian system */
+            i32_sub = 0;
+        } else {
+            /* big-endian system */
+            i32_sub = (sizeof ip.i32 / sizeof ip.i32[0]) - 1;
+        }
+    }
+
+    ip.p = p;
+    return ip.i32[i32_sub];
+}
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_CallBack
+ *
+ * Description:
+ *      Routine called by the server-side callback RPC interface to
+ *      implement passing in callback information.
+ *      table.
+ *
+ * Arguments:
+ *      rx_call    : Ptr to Rx call on which this request came in.
+ *      fidsArrayp : Ptr to array of fids involved.
+ *      cbsArrayp  : Ptr to matching callback info for the fids.
+ *
+ * Returns:
+ *      0 (always).
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *      As advertised.
+ *------------------------------------------------------------------------*/
 /* handle incoming RPC callback breaking message.
  * Called with no locks held.
  */
+int
 SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArrayp)
 {
     int i;
     AFSFid *tfidp;
-        
-    osi_Log0(afsd_logp, "SRXAFSCB_CallBack");
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_CallBack from host 0x%x port %d",
+              ntohl(host),
+              ntohs(port));
 
     for (i=0; i < (long) fidsArrayp->AFSCBFids_len; i++) {
         tfidp = &fidsArrayp->AFSCBFids_val[i];
@@ -238,13 +353,34 @@ SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArray
             cm_RevokeCallback(callp, tfidp);
     }
 
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_InitCallBackState
+ *
+ * Description:
+ *      Routine called by the server-side callback RPC interface to
+ *      implement clearing all callbacks from this host.
+ *
+ * Arguments:
+ *      rx_call : Ptr to Rx call on which this request came in.
+ *
+ * Returns:
+ *      0 (always).
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *      As advertised.
+ *------------------------------------------------------------------------*/
 /* called with no locks by RPC system when a server indicates that it has never
  * heard from us, or for other reasons has had to discard callbacks from us
  * without telling us, e.g. a network partition.
  */
+int
 SRXAFSCB_InitCallBackState(struct rx_call *callp)
 {
     struct sockaddr_in taddr;
@@ -252,8 +388,21 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
     cm_scache_t *scp;
     int hash;
     int discarded;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
 
-    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState");
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_InitCallBackState from host 0x%x port %d",
+              ntohl(host),
+              ntohs(port));
 
     if ((rx_ConnectionOf(callp)) && (rx_PeerOf(rx_ConnectionOf(callp)))) {
        taddr.sin_family = AF_INET;
@@ -288,16 +437,17 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
         * are "rare," hopefully this won't be a problem.
         */
        lock_ObtainWrite(&cm_scacheLock);
-       for (hash = 0; hash < cm_hashTableSize; hash++) {
-            for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
+       for (hash = 0; hash < cm_data.hashTableSize; hash++) {
+            for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
                 cm_HoldSCacheNoLock(scp);
                 lock_ReleaseWrite(&cm_scacheLock);
                 lock_ObtainMutex(&scp->mx);
                 discarded = 0;
-                if (scp->cbServerp != NULL) {
+                if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
                     /* we have a callback, now decide if we should clear it */
                     if (scp->cbServerp == tsp || tsp == NULL) {
-                        osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
+                        osi_Log4(afsd_logp, "InitCallbackState Discarding SCache scp 0x%x vol %u vn %u uniq %u", 
+                                  scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
                         cm_DiscardSCache(scp);
                         discarded = 1;
                     }
@@ -316,89 +466,675 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
        if (tsp) 
             cm_PutServer(tsp);
     }
-
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
-/* just returns if we're up */
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_Probe
+ *
+ * Description:
+ *      Routine called by the server-side callback RPC interface to
+ *      implement ``probing'' the Cache Manager, just making sure it's
+ *      still there.
+ *
+ * Arguments:
+ *      rx_call : Ptr to Rx call on which this request came in.
+ *
+ * Returns:
+ *      0 (always).
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *      As advertised.
+ *------------------------------------------------------------------------*/
+int
 SRXAFSCB_Probe(struct rx_call *callp)
 {
-    osi_Log0(afsd_logp, "SRXAFSCB_Probe - not implemented");
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_Probe from host 0x%x port %d",
+              ntohl(host),
+              ntohs(port));
+
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
-/* debug interface: not implemented */
-SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
-{
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_GetCE64 - not implemented");
-    return RXGEN_OPCODE;
-}
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_GetLock
+ *
+ * Description:
+ *      Routine called by the server-side callback RPC interface to
+ *      implement pulling out the contents of a lock in the lock
+ *      table.
+ *
+ * Arguments:
+ *      a_call   : Ptr to Rx call on which this request came in.
+ *      a_index  : Index of desired lock.
+ *      a_result : Ptr to a buffer for the given lock.
+ *
+ * Returns:
+ *      0 if everything went fine,
+ *      1 if we were given a bad index.
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *      As advertised.
+ *------------------------------------------------------------------------*/
+/* debug interface */
+
+extern osi_rwlock_t cm_aclLock;
+extern osi_rwlock_t buf_globalLock;
+extern osi_rwlock_t cm_callbackLock;
+extern osi_rwlock_t cm_cellLock;
+extern osi_rwlock_t cm_connLock;
+extern osi_rwlock_t cm_daemonLock;
+extern osi_rwlock_t cm_dnlcLock;
+extern osi_rwlock_t cm_scacheLock;
+extern osi_rwlock_t cm_serverLock;
+extern osi_rwlock_t cm_userLock;
+extern osi_rwlock_t cm_utilsLock;
+extern osi_rwlock_t cm_volumeLock;
+extern osi_rwlock_t smb_globalLock;
+extern osi_rwlock_t smb_rctLock;
 
-/* debug interface: not implemented */
+extern osi_mutex_t cm_Freelance_Lock;
+extern osi_mutex_t cm_bufGetMutex;
+extern osi_mutex_t cm_Afsdsbmt_Lock;
+extern osi_mutex_t tokenEventLock;
+extern osi_mutex_t  smb_ListenerLock;
+extern osi_mutex_t smb_RawBufLock;
+extern osi_mutex_t smb_Dir_Watch_Lock;
+
+#define LOCKTYPE_RW     1
+#define LOCKTYPE_MUTEX  2
+static struct _ltable {
+    char *name;
+    char *addr;
+    int  type;
+} ltable[] = {
+    {"cm_scacheLock",    (char*)&cm_scacheLock,         LOCKTYPE_RW},
+    {"buf_globalLock",   (char*)&buf_globalLock,        LOCKTYPE_RW},
+    {"cm_serverLock",    (char*)&cm_serverLock,         LOCKTYPE_RW},
+    {"cm_callbackLock",  (char*)&cm_callbackLock,       LOCKTYPE_RW},
+    {"cm_aclLock",       (char*)&cm_aclLock,            LOCKTYPE_RW},
+    {"cm_cellLock",      (char*)&cm_cellLock,           LOCKTYPE_RW},
+    {"cm_connLock",      (char*)&cm_connLock,           LOCKTYPE_RW},
+    {"cm_userLock",      (char*)&cm_userLock,           LOCKTYPE_RW},
+    {"cm_volumeLock",    (char*)&cm_volumeLock,         LOCKTYPE_RW},
+    {"cm_daemonLock",    (char*)&cm_daemonLock,         LOCKTYPE_RW},
+    {"cm_dnlcLock",      (char*)&cm_dnlcLock,           LOCKTYPE_RW},
+    {"cm_utilsLock",     (char*)&cm_utilsLock,          LOCKTYPE_RW},
+    {"smb_globalLock",   (char*)&smb_globalLock,        LOCKTYPE_RW},
+    {"smb_rctLock",      (char*)&smb_rctLock,           LOCKTYPE_RW},
+    {"cm_Freelance_Lock",(char*)&cm_Freelance_Lock,     LOCKTYPE_MUTEX},
+    {"cm_bufGetMutex",   (char*)&cm_bufGetMutex,        LOCKTYPE_MUTEX},
+    {"cm_Afsdsbmt_Lock", (char*)&cm_Afsdsbmt_Lock,      LOCKTYPE_MUTEX},
+    {"tokenEventLock",   (char*)&tokenEventLock,        LOCKTYPE_MUTEX},
+    {"smb_ListenerLock", (char*)&smb_ListenerLock,      LOCKTYPE_MUTEX},
+    {"smb_RawBufLock",   (char*)&smb_RawBufLock,        LOCKTYPE_MUTEX},
+    {"smb_Dir_Watch_Lock",(char*)&smb_Dir_Watch_Lock,   LOCKTYPE_MUTEX}
+};
+
+int
 SRXAFSCB_GetLock(struct rx_call *callp, long index, AFSDBLock *lockp)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_GetLock - not implemented");
-    return RXGEN_OPCODE;
+    struct _ltable *tl;          /*Ptr to lock table entry */
+    osi_rwlock_t  *rwp;
+    osi_mutex_t   *mtxp;
+    int nentries;               /*Num entries in table */
+    int code;                   /*Return code */
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log3(afsd_logp, "SRXAFSCB_GetLock(%d) from host 0x%x port %d", 
+             index, ntohl(host), ntohs(port));
+
+    nentries = sizeof(ltable) / sizeof(struct _ltable);
+    if (index < 0 || index >= nentries) {
+        /*
+         * Past EOF
+         */
+        code = 1;
+    } else {
+        /*
+         * Found it - copy out its contents.
+         */
+        tl = &ltable[index];
+        strncpy(lockp->name, tl->name, sizeof(lockp->name));
+        lockp->name[sizeof(lockp->name)-1] = '\0';
+        lockp->lock.waitStates = 0;
+        switch ( tl->type ) {
+        case LOCKTYPE_RW:
+            rwp = (osi_rwlock_t *)tl->addr;
+            lockp->lock.exclLocked = rwp->flags;
+            lockp->lock.readersReading = rwp->readers;
+            lockp->lock.numWaiting = rwp->waiters;
+            break;
+        case LOCKTYPE_MUTEX:
+            mtxp = (osi_mutex_t *)tl->addr;
+            lockp->lock.exclLocked = mtxp->flags;
+            lockp->lock.readersReading = 0;
+            lockp->lock.numWaiting = mtxp->waiters;
+            break;
+        }
+        lockp->lock.pid_last_reader = 0;
+        lockp->lock.pid_writer = 0;
+        lockp->lock.src_indicator = 0;
+        code = 0;
+    }
+
+    MUTEX_EXIT(&callp->lock);
+    return code;
 }
 
-/* debug interface: not implemented */
+/* debug interface */
+int
 SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_GetCE - not implemented");
-    return RXGEN_OPCODE;
+    int i;
+    cm_scache_t * scp;
+    int code;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetCE from host 0x%x port %d",
+             ntohl(host), ntohs(port));
+
+    lock_ObtainRead(&cm_scacheLock);
+    for (i = 0; i < cm_data.hashTableSize; i++) {
+        for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+            if (index == 0)
+                goto searchDone;
+            index--;
+        }                       /*Zip through current hash chain */
+    }                           /*Zip through hash chains */
+
+  searchDone:
+    if (scp == NULL) {
+        /*Past EOF */
+        code = 1;
+        goto fcnDone;
+    }
+
+    /*
+     * Copy out the located entry.
+     */
+    memset(cep, 0, sizeof(AFSDBCacheEntry));
+    cep->addr = afs_data_pointer_to_int32(scp);
+    cep->cell = scp->fid.cell;
+    cep->netFid.Volume = scp->fid.volume;
+    cep->netFid.Vnode = scp->fid.vnode;
+    cep->netFid.Unique = scp->fid.unique;
+    cep->lock.waitStates = 0;
+    cep->lock.exclLocked = scp->mx.flags;
+    cep->lock.readersReading = 0;
+    cep->lock.numWaiting = scp->mx.waiters;
+    cep->lock.pid_last_reader = 0;
+    cep->lock.pid_writer = 0;
+    cep->lock.src_indicator = 0;
+    cep->Length = scp->length.LowPart;
+    cep->DataVersion = scp->dataVersion;
+    cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
+    cep->cbExpires = scp->cbExpires;
+    cep->refCount = scp->refCount;
+    cep->opens = scp->openReads;
+    cep->writers = scp->openWrites;
+    switch (scp->fileType) {
+    case CM_SCACHETYPE_FILE:
+        cep->mvstat = 0;
+        break;
+    case CM_SCACHETYPE_MOUNTPOINT:
+        cep->mvstat = 1;
+        break;
+    case CM_SCACHETYPE_DIRECTORY:
+        if (scp->fid.vnode == 1 && scp->fid.unique == 1)
+            cep->mvstat = 2;
+        else
+            cep->mvstat = 3;
+        break;
+    case CM_SCACHETYPE_SYMLINK:
+        cep->mvstat = 4;
+        break;
+    case CM_SCACHETYPE_DFSLINK:
+        cep->mvstat = 5;
+        break;
+    case CM_SCACHETYPE_INVALID:
+        cep->mvstat = 6;
+        break;
+    }
+    cep->states = 0;
+    if (scp->flags & CM_SCACHEFLAG_STATD)
+        cep->states |= 1;
+    if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
+        cep->states |= 4;
+    if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
+        scp->mountPointStringp[0])
+        cep->states |= 8;
+    if (scp->flags & CM_SCACHEFLAG_WAITING)
+        cep->states |= 0x40;
+    code = 0;
+
+    /*
+     * Return our results.
+     */
+  fcnDone:
+    lock_ReleaseRead(&cm_scacheLock);
+
+    MUTEX_EXIT(&callp->lock);
+    return (code);
+}
+
+/* debug interface */
+int
+SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry64 *cep)
+{
+    int i;
+    cm_scache_t * scp;
+    int code;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetCE64 from host 0x%x port %d",
+             ntohl(host), ntohs(port));
+
+    lock_ObtainRead(&cm_scacheLock);
+    for (i = 0; i < cm_data.hashTableSize; i++) {
+        for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+            if (index == 0)
+                goto searchDone;
+            index--;
+        }                       /*Zip through current hash chain */
+    }                           /*Zip through hash chains */
+
+  searchDone:
+    if (scp == NULL) {
+        /*Past EOF */
+        code = 1;
+        goto fcnDone;
+    }
+
+    /*
+     * Copy out the located entry.
+     */
+    memset(cep, 0, sizeof(AFSDBCacheEntry64));
+    cep->addr = afs_data_pointer_to_int32(scp);
+    cep->cell = scp->fid.cell;
+    cep->netFid.Volume = scp->fid.volume;
+    cep->netFid.Vnode = scp->fid.vnode;
+    cep->netFid.Unique = scp->fid.unique;
+    cep->lock.waitStates = 0;
+    cep->lock.exclLocked = scp->mx.flags;
+    cep->lock.readersReading = 0;
+    cep->lock.numWaiting = scp->mx.waiters;
+    cep->lock.pid_last_reader = 0;
+    cep->lock.pid_writer = 0;
+    cep->lock.src_indicator = 0;
+#if !defined(AFS_64BIT_ENV)
+    cep->Length.high = scp->length.HighPart;
+    cep->Length.low = scp->length.LowPart;
+#else
+    cep->Length = ((afs_int64)scp->length.HighPart)<<32 | scp->length.LowPart;
+#endif
+    cep->DataVersion = scp->dataVersion;
+    cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
+    cep->cbExpires = scp->cbExpires;
+    cep->refCount = scp->refCount;
+    cep->opens = scp->openReads;
+    cep->writers = scp->openWrites;
+    switch (scp->fileType) {
+    case CM_SCACHETYPE_FILE:
+        cep->mvstat = 0;
+        break;
+    case CM_SCACHETYPE_MOUNTPOINT:
+        cep->mvstat = 1;
+        break;
+    case CM_SCACHETYPE_DIRECTORY:
+        if (scp->fid.vnode == 1 && scp->fid.unique == 1)
+            cep->mvstat = 2;
+        else
+            cep->mvstat = 3;
+        break;
+    case CM_SCACHETYPE_SYMLINK:
+        cep->mvstat = 4;
+        break;
+    case CM_SCACHETYPE_DFSLINK:
+        cep->mvstat = 5;
+        break;
+    case CM_SCACHETYPE_INVALID:
+        cep->mvstat = 6;
+        break;
+    }
+    cep->states = 0;
+    if (scp->flags & CM_SCACHEFLAG_STATD)
+        cep->states |= 1;
+    if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
+        cep->states |= 4;
+    if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
+        scp->mountPointStringp[0])
+        cep->states |= 8;
+    if (scp->flags & CM_SCACHEFLAG_WAITING)
+        cep->states |= 0x40;
+    code = 0;
+
+    /*
+     * Return our results.
+     */
+  fcnDone:
+    lock_ReleaseRead(&cm_scacheLock);
+
+    MUTEX_EXIT(&callp->lock);
+    return (code);
 }
 
 /* debug interface: not implemented */
+int
 SRXAFSCB_XStatsVersion(struct rx_call *callp, long *vp)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_XStatsVersion - not implemented");
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_XStatsVersion from host 0x%x port %d - not implemented",
+             ntohl(host), ntohs(port));
     *vp = -1;
+
+    MUTEX_EXIT(&callp->lock);
     return RXGEN_OPCODE;
 }
 
 /* debug interface: not implemented */
+int
 SRXAFSCB_GetXStats(struct rx_call *callp, long cvn, long coln, long *srvp, long *timep,
-       AFSCB_CollData *datap)
+                   AFSCB_CollData *datap)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_GetXStats - not implemented");
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetXStats from host 0x%x port %d - not implemented",
+             ntohl(host), ntohs(port));
+
+    MUTEX_EXIT(&callp->lock);
     return RXGEN_OPCODE;
 }
 
-/* debug interface: not implemented */
+int
 SRXAFSCB_InitCallBackState2(struct rx_call *callp, struct interfaceAddr* addr)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState2 - not implemented");
-    return RXGEN_OPCODE;
+    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState2 ->");
+
+    return SRXAFSCB_InitCallBackState(callp);
 }
 
-/* debug interface: not implemented */
+/* debug interface */
+int
 SRXAFSCB_WhoAreYou(struct rx_call *callp, struct interfaceAddr* addr)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_WhoAreYou - not implemented");
-    return RXGEN_OPCODE;
+    int i;
+    int cm_noIPAddr;         /* number of client network interfaces */
+    int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
+    int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
+    int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
+    int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
+    long code;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    /* get network related info */
+    cm_noIPAddr = CM_MAXINTERFACE_ADDR;
+    code = syscfg_GetIFInfo(&cm_noIPAddr,
+                             cm_IPAddr, cm_SubnetMask,
+                             cm_NetMtu, cm_NetFlags);
+
+    /* return all network interface addresses */
+    osi_Log2(afsd_logp, "SRXAFSCB_WhoAreYou from host 0x%x port %d",
+              ntohl(host),
+              ntohs(port));
+
+    addr->numberOfInterfaces = cm_noIPAddr;
+    addr->uuid = cm_data.Uuid;
+    for ( i=0; i < cm_noIPAddr; i++ ) {
+        addr->addr_in[i] = cm_IPAddr[i];
+        addr->subnetmask[i] = cm_SubnetMask[i];
+        addr->mtu[i] = cm_NetMtu[i];
+    }
+    
+    MUTEX_EXIT(&callp->lock);
+
+    return 0;
 }
 
-/* debug interface: not implemented */
+int
 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 - not implemented");
-    return RXGEN_OPCODE;
+    char *p = NULL;
+
+    if (UuidToString((UUID *)serverUuid, &p) == RPC_S_OK) {
+        osi_Log1(afsd_logp, "SRXAFSCB_InitCallBackState3 %s ->",p);
+        RpcStringFree(&p);
+    } else
+        osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 - no server Uuid ->");
+
+    return SRXAFSCB_InitCallBackState(callp);
 }
 
-/* debug interface: not implemented */
+/* debug interface */
+int
 SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
 {
-    /* XXXX */
-    osi_Log0(afsd_logp, "SRXAFSCB_ProbeUuid - not implemented");
-    return RXGEN_OPCODE;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+    char *p,*q;
+    int code = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    if ( !afs_uuid_equal(&cm_data.Uuid, clientUuid) ) {
+        UuidToString((UUID *)&cm_data.Uuid, &p);
+        UuidToString((UUID *)clientUuid, &q);
+        osi_Log4(afsd_logp, "SRXAFSCB_ProbeUuid %s != %s from host 0x%x port %d", 
+                  osi_LogSaveString(afsd_logp,p), 
+                  osi_LogSaveString(afsd_logp,q),
+                  ntohl(host),
+                  ntohs(port));
+        RpcStringFree(&p);
+        RpcStringFree(&q);
+
+        code = 1;       /* failure */
+    } else
+        osi_Log2(afsd_logp, "SRXAFSCB_ProbeUuid (success) from host 0x%x port %d",
+                  ntohl(host),
+                  ntohs(port));
+
+    MUTEX_EXIT(&callp->lock);
+    return code;
+}
+
+/* debug interface */
+int 
+SRXAFSCB_GetCellByNum(struct rx_call *callp, afs_int32 a_cellnum,
+                      char **a_name, serverList *a_hosts)
+{
+    afs_int32 sn;
+    cm_cell_t * cellp;
+    cm_serverRef_t * serverRefp; 
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log3(afsd_logp, "SRXAFSCB_GetCellByNum(%d) from host 0x%x port %d",
+             a_cellnum, ntohl(host), ntohs(port));
+
+    a_hosts->serverList_val = 0;
+    a_hosts->serverList_len = 0;
+
+    cellp = cm_FindCellByID(a_cellnum);
+    if (!cellp) {
+        *a_name = strdup("");
+        MUTEX_EXIT(&callp->lock);
+        return 0;
+    }
+
+    lock_ObtainRead(&cm_serverLock);
+    *a_name = strdup(cellp->name);
+
+    for ( sn = 0, serverRefp = cellp->vlServersp; 
+          sn < AFSMAXCELLHOSTS && serverRefp;
+          sn++, serverRefp = serverRefp->next);
+
+    a_hosts->serverList_len = sn;
+    a_hosts->serverList_val = (afs_int32 *)osi_Alloc(sn * sizeof(afs_int32));
+
+    for ( sn = 0, serverRefp = cellp->vlServersp; 
+          sn < AFSMAXCELLHOSTS && serverRefp;
+          sn++, serverRefp = serverRefp->next)
+    {
+        a_hosts->serverList_val[sn] = ntohl(serverRefp->server->addr.sin_addr.s_addr);
+    }
+
+    lock_ReleaseRead(&cm_serverLock);
+    MUTEX_EXIT(&callp->lock);
+    return 0;
+}
+
+/* debug interface */
+int 
+SRXAFSCB_TellMeAboutYourself( struct rx_call *callp, 
+                              struct interfaceAddr *addr,
+                              Capabilities * capabilities)
+{
+    int i;
+    afs_int32 *dataBuffP;
+    afs_int32 dataBytes;
+    int cm_noIPAddr;         /* number of client network interfaces */
+    int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
+    int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
+    int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
+    int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
+    long code;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    /* get network related info */
+    cm_noIPAddr = CM_MAXINTERFACE_ADDR;
+    code = syscfg_GetIFInfo(&cm_noIPAddr,
+                             cm_IPAddr, cm_SubnetMask,
+                             cm_NetMtu, cm_NetFlags);
+
+    osi_Log2(afsd_logp, "SRXAFSCB_TellMeAboutYourself from host 0x%x port %d",
+              ntohl(host),
+              ntohs(port));
+
+    /* return all network interface addresses */
+    addr->numberOfInterfaces = cm_noIPAddr;
+    addr->uuid = cm_data.Uuid;
+    for ( i=0; i < cm_noIPAddr; i++ ) {
+        addr->addr_in[i] = cm_IPAddr[i];
+        addr->subnetmask[i] = cm_SubnetMask[i];
+        addr->mtu[i] = cm_NetMtu[i];
+    }
+
+    dataBytes = 1 * sizeof(afs_int32);
+    dataBuffP = (afs_int32 *) osi_Alloc(dataBytes);
+    dataBuffP[0] = CAPABILITY_ERRORTRANS;
+    capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
+    capabilities->Capabilities_val = dataBuffP;
+
+    MUTEX_EXIT(&callp->lock);
+
+    return 0;
 }
 
 /*------------------------------------------------------------------------
@@ -424,15 +1160,31 @@ SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
  *------------------------------------------------------------------------*/
 
 int SRXAFSCB_GetServerPrefs(
-    struct rx_call *a_call,
+    struct rx_call *callp,
     afs_int32 a_index,
     afs_int32 *a_srvr_addr,
     afs_int32 *a_srvr_rank)
 {
-    osi_Log0(afsd_logp, "SRXAFSCB_GetServerPrefs - not implemented");
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
+
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetServerPrefs from host 0x%x port %d - not implemented",
+              ntohl(host),
+              ntohs(port));
 
     *a_srvr_addr = 0xffffffff;
     *a_srvr_rank = 0xffffffff;
+
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
@@ -458,20 +1210,31 @@ int SRXAFSCB_GetServerPrefs(
  *      As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetCellServDB(
-    struct rx_call *a_call,
-    afs_int32 a_index,
-    char **a_name,
-    serverList *a_hosts)
+int SRXAFSCB_GetCellServDB(struct rx_call *callp, afs_int32 index, char **a_name, 
+                           serverList *a_hosts)
 {
     char *t_name;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
 
-    osi_Log0(afsd_logp, "SRXAFSCB_GetCellServDB - not implemented");
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetCellServDB from host 0x%x port %d - not implemented",
+             ntohl(host), ntohs(port));
 
     t_name = (char *)malloc(AFSNAMEMAX);
     t_name[0] = '\0';
     *a_name = t_name;
     a_hosts->serverList_len = 0;
+
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
@@ -495,22 +1258,34 @@ int SRXAFSCB_GetCellServDB(
  *      As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetLocalCell(
-    struct rx_call *a_call,
-    char **a_name)
+int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
 {
     char *t_name;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
 
-    osi_Log0(afsd_logp, "SRXAFSCB_GetLocalCell");
+    MUTEX_ENTER(&callp->lock);
 
-    if (cm_rootCellp) {
-       t_name = (char *)malloc(strlen(cm_rootCellp->namep)+1);
-        strcpy(t_name, cm_rootCellp->namep);
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetLocalCell from host 0x%x port %d",
+             ntohl(host), ntohs(port));
+
+    if (cm_data.rootCellp) {
+       t_name = (char *)malloc(strlen(cm_data.rootCellp->name)+1);
+        strcpy(t_name, cm_data.rootCellp->name);
     } else {
        t_name = (char *)malloc(1);
        t_name[0] = '\0';
     }
     *a_name = t_name;
+
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
@@ -576,19 +1351,29 @@ static void afs_MarshallCacheConfig(
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetCacheConfig(a_call, callerVersion, serverVersion,
-                           configCount, config)
-struct rx_call *a_call;
-afs_uint32 callerVersion;
-afs_uint32 *serverVersion;
-afs_uint32 *configCount;
-cacheConfig *config;
+int SRXAFSCB_GetCacheConfig(struct rx_call *callp,
+                            afs_uint32 callerVersion,
+                            afs_uint32 *serverVersion,
+                            afs_uint32 *configCount,
+                            cacheConfig *config)
 {
     afs_uint32 *t_config;
     size_t allocsize;
     extern cm_initparams_v1 cm_initParams;
+    struct rx_connection *connp;
+    struct rx_peer *peerp;
+    unsigned long host = 0;
+    unsigned short port = 0;
 
-    osi_Log0(afsd_logp, "SRXAFSCB_GetCacheConfig - version 1 only");
+    MUTEX_ENTER(&callp->lock);
+
+    if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
+        host = rx_HostOf(peerp);
+        port = rx_PortOf(peerp);
+    }
+
+    osi_Log2(afsd_logp, "SRXAFSCB_GetCacheConfig from host 0x%x port %d - version 1 only",
+             ntohl(host), ntohs(port));
 
     /*
      * Currently only support version 1
@@ -603,6 +1388,7 @@ cacheConfig *config;
     config->cacheConfig_val = t_config;
     config->cacheConfig_len = allocsize/sizeof(afs_uint32);
 
+    MUTEX_EXIT(&callp->lock);
     return 0;
 }
 
@@ -644,25 +1430,25 @@ int cm_HaveCallback(cm_scache_t *scp)
            return 1;
         }
 
-           lock_ObtainMutex(&cm_Freelance_Lock);
-           fdc = cm_fakeDirCallback;
-           fgc = cm_fakeGettingCallback;
-           lock_ReleaseMutex(&cm_Freelance_Lock);
+        lock_ObtainMutex(&cm_Freelance_Lock);
+        fdc = cm_fakeDirCallback;
+        fgc = cm_fakeGettingCallback;
+        lock_ReleaseMutex(&cm_Freelance_Lock);
            
-           if (fdc==1) {       // first call since init
-               return 0;
-           } else if (fdc==2 && !fgc) {        // we're in good shape
-               if (cm_getLocalMountPointChange()) {    // check for changes
-                   cm_clearLocalMountPointChange(); // clear the changefile
-            lock_ReleaseMutex(&scp->mx);      // this is re-locked in reInitLocalMountPoints
-                   cm_reInitLocalMountPoints();        // start reinit
-            lock_ObtainMutex(&scp->mx);      // now get the lock back 
-                   return 0;
-               }
-               return 1;                       // no change
-           }
-           return 0;
-       }
+        if (fdc==1) {  // first call since init
+            return 0;
+        } else if&nbs