Fixed package callers tracking.
[www.jankratochvil.net.git] / project / captive / doc / CacheManager.pm
1 # $Id$
2 # Captive project doc Cache Manager page Perl template.
3 # Copyright (C) 2003-2005 Jan Kratochvil <project-www.jankratochvil.net@jankratochvil.net>
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; exactly version 2 of June 1991 is required
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
19 package project::captive::doc::CacheManager;
20 require 5.6.0;  # at least 'use warnings;' but we need some 5.6.0+ modules anyway
21 our $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; };
22 our $CVS_ID=q$Id$;
23 use strict;
24 use warnings;
25
26 use My::Web;
27 require CGI;
28
29
30 sub handler
31 {
32         BEGIN { Wuse 'project::captive::doc::Macros'; }
33 project::captive::doc::Macros->init(
34                 "title"=>'Captive NTFS Developer Documentation: NT Cache Manager',
35                 "rel_prev"=>'Reverse.pm',
36                 "rel_next"=>'Details.pm',
37                 );
38
39
40 print <<"HERE";
41
42
43 <h1 id="cache_manager">NT Cache Manager</h1>
44
45         <p>Although there exist some 3rd party documents about
46         <span class="productname">NT Cache Manager</span> W32 subsystem such as
47         <span class="productname">@{[ a_href 'http://www.osr.com/ntinsider/1996/cacheman.htm',
48                         'The NT Cache Manager Description' ]}</span> or
49         <span class="productname">@{[ a_href 'http://www.winntmag.com/Articles/Print.cfm?ArticleID=3864',
50                         'Learn About NT'."'".'s&nbsp;File-system Cache' ]}</span>
51         they are definitely insufficient for compatible
52         <span class="productname">NT Cache Manager</span> reimplementation.</p>
53
54         <p><span class="productname">NT Cache Manager</span> is about mapping
55         filesystem objects such as regular file data, filesystem bitmap or
56         journalling zone (log file). It is also being used by the filesystem for
57         mapping of virtual volume files representing the whole underlying
58         filesystem device.</p>
59
60         <p>The original W32 <span class="productname">NT Cache Manager</span>
61         is much more complicated as it must coordinate its effort with
62         other W32 subsystems like mapping of executable files
63         (<span class="type">ImageSectionObject</span>), insufficient system
64         resources from <span class="productname">NT Memory Manager</span>
65         or general effort to perform caching features for system performance.</p>
66         <p><span class="productname">NT Cache Manager</span> of this project has much
67         simpler goal - it just needs to provide compatible
68         <span class="productname">NT Cache Manager</span> functionality while
69         the other goals of its W32 counterpart are left to be successfuly handled
70         by UNIX OS in much more efficient way.</p>
71
72         @{[ doc_img 'dia/cache-manager',
73                         '<span class="productname">NT Cache Manager</span> Architecture' ]}
74
75         <p>Cache Manager objects are always bound to
76         <span class="type">FCB</span> (File Control Block).
77         <span class="type">FileObject</span> (or its associated
78         <span class="type">HANDLE</span>) serve only as reference
79         to <span class="type">FCB</span> and there can be multiple
80         <span class="type">FileObject</span>/<span class="type">HANDLE</span>
81         items for one <span class="type">FCB</span>. It is a bit misleading
82         you must use <span class="type">FileObject</span> pointer while calling
83         most of the Cache Manager functions.</p>
84
85         <p>Before using any other Cache Manager functions you must first call
86         <span class="function">CcInitializeCacheMap()</span>. You must give the
87         maximum mapped object offset. Each mapped object byte must have at most one
88         mapped memory location - no shared pages are allowed. Also any subsequent
89         mapping request is expected to be mapped into continuous memory region.
90         It implies you must reserve the memory region for possible future mapping
91         during the initial <span class="function">CcInitializeCacheMap()</span>
92         moment sized according to the given maximum mapped object offset. 
93         This is the approach currently implemented by this project although it
94         cannot be used for 3rd party <span class="fname">ext2fsd.sys</span>
95         driver as it initialized Cache Manager by the whole media device size
96         and it surprisingly succeeds for original
97         <span class="productname">Microsoft Windows</span> 
98         <span class="productname">Cache Manager</span>.
99         I expect the space reservation should be postponed to the first mapping
100         request and expect no multiple mappings will be done in the case
101         of memory-exceeding <span class="function">CcInitializeCacheMap()</span>
102         reservation request. <span class="function">CcSetFileSizes()</span>
103         changing the reserved memory area size may assume no existing Map
104         or Pin mappings exist. Only in the case of 
105         <span class="constant">FO_STREAM_FILE</span> (virtual device file)
106         it is permitted to extend mapped size even in the case of existing
107         (and dirty) Map or Pin mappings.</p>
108
109         <p><span class="type">PCACHE_MANAGER_CALLBACKS</span> argument can be
110         safely ignored:</p>
111
112         <dl>
113                 <dt><span class="function">AcquireForReadAhead()</span>/<span class="function">ReleaseFromReadAhead()</span></dt>
114                 <dd>
115                         <p>As any readahead functionality is optional these entries are
116                         never used by Cache Manager implementation of this project.</p>
117                 </dd>
118
119                 <dt><span class="function">AcquireForLazyWrite()</span>/<span class="function">ReleaseFromLazyWrite()</span></dt>
120                 <dd>
121                         <p>Even the write-behind functionality is optional for Cache Manager.
122                         It is being done in asynchronous way in the original
123                         <span class="productname">Microsoft Windows</span>
124                         <span class="productname">Cache Manager</span>.
125                         implementation and it is ignored by Cache Manager implementation of
126                         this project.</p>
127
128                         <p>Cache Manager does not need to write any data if not explicitely
129                         requested by the driver. It is even expected to silently drop any
130                         pending dirty data blocks during filesystem shutdown.
131                         Forced dirty block write by function
132                         <span class="function">CcFlushCache()</span> should be written without
133                         any wrapping surrounding
134                         <span class="function">AcquireForLazyWrite()</span>/<span class="function">ReleaseFromLazyWrite()</span>
135                         pair.</p>
136                 </dd>
137         </dl>
138
139         <p><span class="function">CcUninitializeCacheMap()</span> is just
140         a suggestion for Cache Manager that driver will no longer reference
141         given <span class="type">SharedCacheMap</span>. The uninitialization
142         can be postponed to any later moment in original 
143         <span class="productname">Microsoft Windows</span> 
144         <span class="productname">Cache Manager</span>
145         as it may be locked by existing
146         <span class="type">ImageSectionObject</span>
147         of some file being executed etc.
148         <span id="sharedcachemap_leak">It is fatal to destroy
149         <span class="type">SharedCacheMap</span></span>
150         in the moment you see no other
151         references to it as the driver will access it for some moment
152         even after <span class="function">CcUninitializeCacheMap()</span>.
153         I am not sure if it is a bug of the driver or whether there are some rules
154         how long after <span class="function">CcUninitializeCacheMap()</span>
155         completion given <span class="type">SharedCacheMap</span> still exists.
156         Fortunately it is safe to never destroy
157         <span class="type">SharedCacheMap</span> and leave it leaked - everything
158         gets clean in the
159         @{[ a_href 'Details.pm#sandbox','sandboxed environment' ]} soon anyway.</p>
160
161         <p>There exist Map and Pin type objects for each
162         <span class="type">SharedCacheMap</span> although they look very similiar.
163         Only these objects give you access to any memory data
164         &mdash; <span class="type">SharedCacheMap</span> only reserved the space
165         to ensure continuous mapping of the forthcoming mappings but it did not map
166         any data into it.</p>
167
168         <p>Mapping of 'new' Map or Pin will create the new object only in the case
169         no such mapping exists now. Otherwise you will just get the reference to
170         the existing object with increased usecount.</p>
171
172         <dl>
173                 <dt>Map</dt>
174                 <dd>
175                         <p>Map mapping is always at most one for each
176                         <span class="type">SharedCacheMap</span>. Base offset/length of such
177                         mapping have no meaning as there can be only single Map.</p>
178
179                         <p>Apparently Map size can be arbitrary long according
180                         to its <span class="type">SharedCacheMap</span> reserved space.</p>
181
182                         <p>You cannot modify the memory mapped by Map in any way.
183                         As it is the same memory area (address) as the pages used by Pin
184                         objects you always access the last modified version by possible
185                         Pin of the same page.</p>
186                 </dd>
187
188                 <dt>Pin</dt>
189                 <dd>
190                         <p>Pin mapping always represents just one physical page
191                         (<span class="constant">PAGE_SIZE</span> &ndash; 4096 for i386).
192                         Its base offset/length can be safely extended to be aligned to the
193                         requested page.</p>
194
195                         <p>Pin can have associated pair of oldest and newest
196                         <span class="type">LSN</span> (Linear Sequence Number). It can be
197                         set by <span class="function">CcSetDirtyPinnedData()</span>
198                         and Cache Manager always tracks the lowest and highest
199                         reported <span class="type">LSN</span> for each page.
200                         <span class="type">LSN</span> is assumed to be
201                         <span class="constant">0</span> if not set.</p>
202
203                         <p>Any existing Pin mapping will be reused for further mappings
204                         as long as it is not ThreadOwned. In the moment you use
205                         <span class="function">CcSetBcbOwnerPointer()</span> you will detach
206                         the associated Pin pages from its
207                         <span class="type">SharedCacheMap</span>.
208                         Although they will further act as valid Pin mappings they will be no
209                         longer reused during new Pin mapping of the same page.
210                         There can exist multiple Pin mappings of the same page (although
211                         sharing the same memory space). This detaching must be implemented
212                         even in the
213                         @{[ a_href 'Details.pm#synchronous','single-threaded' ]} W32 implementation
214                         of this project as it is affecting the behaviour of Cache Manager.
215                         It was never
216                         @{[ a_href 'CacheManager.pm#TraceFS','seen' ]} how to behave if multiple dirty Pin
217                         mappings of the same page exist.</p>
218                 </dd>
219         </dl>
220
221         <p>Only the pages not yet present in the memory must be read from the disk.
222         You must not read any pages you do not need to as the driver does not
223         expect it and it would corrupt its data buffers. There is just a&nbsp;strict
224         difference between <span class="function">CcPinRead()</span> and
225         <span class="function">CcPinMappedData()</span> function calls where
226         <span class="function">CcPinRead()</span> is required to re-read its data
227         blocks even if they were currently already Map mapped (unless it was already
228         also Pin mapped at least once). On the opposite side
229         <span class="function">CcPinMappedData()</span> must not re-read the given
230         blocks, moreover it blocks are required to be already Map mapped by the caller.</p>
231
232         <p>Cache Manager of this project will destroy Pin or Map mappings after
233         their last unreferencing (in opposite of
234         @{[ a_href '#sharedcachemap_leak','leaked <span class="type">SharedCacheMap</span>' ]}).
235         Despite it any dirty pages may still be held as the pages
236         (including their <span class="type">LSN</span>s) are cached associated
237         with <span class="type">SharedCacheMap</span>. It may be also possible
238         original <span class="productname">Microsoft Windows</span> 
239         <span class="productname">Cache Manager</span>
240         postpones Pin mapping destroy to later time but it does not matter.</p>
241
242
243         <h2 id="TraceFS">TraceFS NT Cache Manager Tracer</h2>
244
245                 <p>@{[ a_href '#cache_manager','Cache Manager behaviour' ]} would be hard
246                 to analyze just by @{[ a_href '#reverse','reverse engineering' ]} as it
247                 is pretty complicated code cooperating with many other W32 kernel
248                 subsystems. It was chosen as easier way to trace it instead and validate
249                 all the Cache Manager assumptions by Cache Manager simulator.</p>
250
251                 @{[ doc_img 'dia/TraceFS','TraceFS Hooking' ]}
252
253                 <p>You must prepare your driver to be hooked
254                 (<span class="fname">ntfs.sys</span> in this case):</p>
255
256                 <blockquote class="command">
257                         <p>@{[ captive_srcfile './src/TraceFS/hookfs.pl' ]} ntfs.sys ./src/TraceFS/TraceFS-W32/TraceFS.sys &gt;hooked/ntfs.sys</p>
258                 </blockquote>
259
260                 <p>This <span class="fname">hooked/ntfs.sys</span> file must be replaced
261                 in the <span class="fname">%System32%\\drivers</span> directory.
262                 Beware as
263                 <span class="productname">Microsoft Windows</span>
264                 has many backups of these system files such as
265                 <span class="fname">%System32%\\dllcache</span> &mdash; delete them
266                 all!</p>
267
268                 <p>You also need to install
269                 <span class="fname">./src/TraceFS/TraceFS-W32/TraceFS.sys</span>
270                 into <span class="fname">%System32%\\drivers</span> directory
271                 and import <span class="fname">TraceFS/TraceFS-W32/TraceFS.reg</span>
272                 registry file to initialize the debug driver during system boot.</p>
273
274                 <p>You can now pray a bit and snap the resulting Cache Manager tracing
275                 from <span class="productname">WinDbg</span> by
276                 @{[ a_href 'Reverse.pm#WinDbg','W32 remote kernel debugging' ]}:</p>
277
278                 @{[ doc_img 'ntdebug-windbg-boot','Successfuly connected <span class="productname">WinDbg</span>' ]}
279
280                 <p>The resulting trace file should be processed by
281                 @{[ captive_srcfile './src/TraceFS/checktrace.pl' ]} Perl Cache Manager
282                 implementation to validate its assumptions about Cache Manager behaviour.
283                 Any seen incompatibilies will be reported &mdash; your target is to reach
284                 as few error messages as possible.</p>
285
286                 <p>KNOWN BUGS: Combination of message synchronization primitives and
287                 implemented refusal to create journalling thread of
288                 <span class="fname">ntfs.sys</span>
289                 causes fatal system lockup in several advanced operations
290                 such as setting compression attribute. Despite it more common operations
291                 can be successfuly traced during the whole
292                 <span class="productname">Microsoft Windows</span>
293                 session including its final shutdown and such traces provide enough
294                 material to be food to
295                 @{[ captive_srcfile './src/TraceFS/checktrace.pl' ]} Perl Cache Manager
296                 validator.</p>
297
298                 <h3 id="TraceFS_general">TraceFS for general API tracing</h3>
299
300                         <p>Although TraceFS was up to now used only for tracing of
301                         <span class="productname">NT Cache Manager</span> it can be easily
302                         used ever for any other NT kernel API tracing. You need to provide
303                         appropriate function wrappers in the main source file
304                         @{[ captive_srcfile './src/TraceFS/TraceFS-W32/TraceFS.c' ]}.
305                         Original system functions being wrapped should be called with their
306                         original name. Your wrapping functions should have the first letter
307                         of their name replaced by character
308                         <span class="command">'T'</span>. Therefore wrapping of
309                         <span class="function">CcInitializeCacheMap()</span> must be
310                         done by your function
311                         <span class="function">TcInitializeCacheMap()</span>.
312                         Prototypes of both the wrapping and wrapped functions must be the same.
313                         You must also export all the wrapped functions by
314                         @{[ captive_srcfile './src/TraceFS/TraceFS-W32/TraceFS.def' ]}.
315                         @{[ captive_srcfile './src/TraceFS/hookfs.pl' ]} has no hardcoded
316                         function names &ndash; it will hook exactly the exported entries.</p>
317
318                         <p>Framework for thread synchronizations and debug tracing is provided to
319                         prevent mangling of messages while running by multiple threads at once.
320                         Testing was done just on uniprocessor machine, SMP kernel may need some
321                         fixes.</p>
322                 
323
324 HERE
325
326
327 project::captive::doc::Macros->footer();
328 }
329 1;