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