%!
%%BoundingBox: (atend)
%%Pages: (atend)
%%DocumentFonts: (atend)
%%EndComments
%
% FrameMaker PostScript Prolog 3.0, for use with FrameMaker 3.0
% Copyright (c) 1986,87,89,90,91 by Frame Technology Corporation.
% All rights reserved.
%
% Known Problems:
% Due to bugs in Transcript, the 'PS-Adobe-' is omitted from line 1
/FMversion (3.0) def
% Set up Color vs. Black-and-White
/FMPrintInColor systemdict /colorimage known
systemdict /currentcolortransfer known or def
% Uncomment this line to force b&w on color printer
% /FMPrintInColor false def
/FrameDict 295 dict def
systemdict /errordict known not {/errordict 10 dict def
errordict /rangecheck {stop} put} if
% The readline in 23.0 doesn't recognize cr's as nl's on AppleTalk
FrameDict /tmprangecheck errordict /rangecheck get put
errordict /rangecheck {FrameDict /bug true put} put
FrameDict /bug false put
mark
% Some PS machines read past the CR, so keep the following 3 lines together!
currentfile 5 string readline
00
0000000000
cleartomark
errordict /rangecheck FrameDict /tmprangecheck get put
FrameDict /bug get {
/readline {
/gstring exch def
/gfile exch def
/gindex 0 def
{
gfile read pop
dup 10 eq {exit} if
dup 13 eq {exit} if
gstring exch gindex exch put
/gindex gindex 1 add def
} loop
pop
gstring 0 gindex getinterval true
} def
} if
/FMVERSION {
FMversion ne {
/Times-Roman findfont 18 scalefont setfont
100 100 moveto
(FrameMaker version does not match postscript_prolog!)
dup =
show showpage
} if
} def
/FMLOCAL {
FrameDict begin
0 def
end
} def
/gstring FMLOCAL
/gfile FMLOCAL
/gindex FMLOCAL
/orgxfer FMLOCAL
/orgproc FMLOCAL
/organgle FMLOCAL
/orgfreq FMLOCAL
/yscale FMLOCAL
/xscale FMLOCAL
/manualfeed FMLOCAL
/paperheight FMLOCAL
/paperwidth FMLOCAL
/FMDOCUMENT {
array /FMfonts exch def
/#copies exch def
FrameDict begin
0 ne dup {setmanualfeed} if
/manualfeed exch def
/paperheight exch def
/paperwidth exch def
/yscale exch def
/xscale exch def
currenttransfer cvlit /orgxfer exch def
currentscreen cvlit /orgproc exch def
/organgle exch def /orgfreq exch def
setpapername
manualfeed {true} {papersize} ifelse
{manualpapersize} {false} ifelse
{desperatepapersize} if
end
} def
/pagesave FMLOCAL
/orgmatrix FMLOCAL
/landscape FMLOCAL
/FMBEGINPAGE {
FrameDict begin
/pagesave save def
3.86 setmiterlimit
/landscape exch 0 ne def
landscape {
90 rotate 0 exch neg translate pop
}
{pop pop}
ifelse
xscale yscale scale
/orgmatrix matrix def
gsave
} def
/FMENDPAGE {
grestore
pagesave restore
end
showpage
} def
/FMFONTDEFINE {
FrameDict begin
findfont
ReEncode
1 index exch
definefont
FMfonts 3 1 roll
put
end
} def
/FMFILLS {
FrameDict begin
array /fillvals exch def
end
} def
/FMFILL {
FrameDict begin
fillvals 3 1 roll put
end
} def
/FMNORMALIZEGRAPHICS {
newpath
0.0 0.0 moveto
1 setlinewidth
0 setlinecap
0 0 0 sethsbcolor
0 setgray
} bind def
/fx FMLOCAL
/fy FMLOCAL
/fh FMLOCAL
/fw FMLOCAL
/llx FMLOCAL
/lly FMLOCAL
/urx FMLOCAL
/ury FMLOCAL
/FMBEGINEPSF {
end
/FMEPSF save def
/showpage {} def
FMNORMALIZEGRAPHICS
[/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall
fx fy translate
rotate
fw urx llx sub div fh ury lly sub div scale
llx neg lly neg translate
} bind def
/FMENDEPSF {
FMEPSF restore
FrameDict begin
} bind def
FrameDict begin
/setmanualfeed {
%%BeginFeature *ManualFeed True
statusdict /manualfeed true put
%%EndFeature
} def
/max {2 copy lt {exch} if pop} bind def
/min {2 copy gt {exch} if pop} bind def
/inch {72 mul} def
/pagedimen {
paperheight sub abs 16 lt exch
paperwidth sub abs 16 lt and
{/papername exch def} {pop} ifelse
} def
/papersizedict FMLOCAL
/setpapername {
/papersizedict 14 dict def
papersizedict begin
/papername /unknown def
/Letter 8.5 inch 11.0 inch pagedimen
/LetterSmall 7.68 inch 10.16 inch pagedimen
/Tabloid 11.0 inch 17.0 inch pagedimen
/Ledger 17.0 inch 11.0 inch pagedimen
/Legal 8.5 inch 14.0 inch pagedimen
/Statement 5.5 inch 8.5 inch pagedimen
/Executive 7.5 inch 10.0 inch pagedimen
/A3 11.69 inch 16.5 inch pagedimen
/A4 8.26 inch 11.69 inch pagedimen
/A4Small 7.47 inch 10.85 inch pagedimen
/B4 10.125 inch 14.33 inch pagedimen
/B5 7.16 inch 10.125 inch pagedimen
end
} def
/papersize {
papersizedict begin
/Letter {lettertray letter} def
/LetterSmall {lettertray lettersmall} def
/Tabloid {11x17tray 11x17} def
/Ledger {ledgertray ledger} def
/Legal {legaltray legal} def
/Statement {statementtray statement} def
/Executive {executivetray executive} def
/A3 {a3tray a3} def
/A4 {a4tray a4} def
/A4Small {a4tray a4small} def
/B4 {b4tray b4} def
/B5 {b5tray b5} def
/unknown {unknown} def
papersizedict dup papername known {papername} {/unknown} ifelse get
end
/FMdicttop countdictstack 1 add def
statusdict begin stopped end
countdictstack -1 FMdicttop {pop end} for
} def
/manualpapersize {
papersizedict begin
/Letter {letter} def
/LetterSmall {lettersmall} def
/Tabloid {11x17} def
/Ledger {ledger} def
/Legal {legal} def
/Statement {statement} def
/Executive {executive} def
/A3 {a3} def
/A4 {a4} def
/A4Small {a4small} def
/B4 {b4} def
/B5 {b5} def
/unknown {unknown} def
papersizedict dup papername known {papername} {/unknown} ifelse get
end
stopped
} def
/desperatepapersize {
statusdict /setpageparams known
{
paperwidth paperheight 0 1
statusdict begin
{setpageparams} stopped pop
end
} if
} def
/savematrix {
orgmatrix currentmatrix pop
} bind def
/restorematrix {
orgmatrix setmatrix
} bind def
/dmatrix matrix def
/dpi 72 0 dmatrix defaultmatrix dtransform
dup mul exch dup mul add sqrt def
/freq dpi 18.75 div 8 div round dup 0 eq {pop 1} if 8 mul dpi exch div def
/sangle 1 0 dmatrix defaultmatrix dtransform exch atan def
/DiacriticEncoding [
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl
/numbersign /dollar /percent /ampersand /quotesingle /parenleft
/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one
/two /three /four /five /six /seven /eight /nine /colon /semicolon
/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K
/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash
/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h
/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar
/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute
/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis
/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis
/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve
/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex
/udieresis /dagger /.notdef /cent /sterling /section /bullet
/paragraph /germandbls /registered /copyright /trademark /acute
/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef
/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown
/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef
/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde
/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright
/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis
/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl
/periodcentered /quotesinglbase /quotedblbase /perthousand
/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute
/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve
/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron
/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron
] def
/ReEncode {
dup
length
dict begin
{
1 index /FID ne
{def}
{pop pop} ifelse
} forall
0 eq {/Encoding DiacriticEncoding def} if
currentdict
end
} bind def
/graymode true def
/bwidth FMLOCAL
/bpside FMLOCAL
/bstring FMLOCAL
/onbits FMLOCAL
/offbits FMLOCAL
/xindex FMLOCAL
/yindex FMLOCAL
/x FMLOCAL
/y FMLOCAL
/setpattern {
/bwidth exch def
/bpside exch def
/bstring exch def
/onbits 0 def /offbits 0 def
freq sangle landscape {90 add} if
{/y exch def
/x exch def
/xindex x 1 add 2 div bpside mul cvi def
/yindex y 1 add 2 div bpside mul cvi def
bstring yindex bwidth mul xindex 8 idiv add get
1 7 xindex 8 mod sub bitshift and 0 ne
{/onbits onbits 1 add def 1}
{/offbits offbits 1 add def 0}
ifelse
}
setscreen
{} settransfer
offbits offbits onbits add div FMsetgray
/graymode false def
} bind def
/grayness {
FMsetgray
graymode not {
/graymode true def
orgxfer cvx settransfer
orgfreq organgle orgproc cvx setscreen
} if
} bind def
/HUE FMLOCAL
/SAT FMLOCAL
/BRIGHT FMLOCAL
/Colors FMLOCAL
FMPrintInColor
{
/HUE 0 def
/SAT 0 def
/BRIGHT 0 def
% array of arrays Hue and Sat values for the separations [HUE BRIGHT]
/Colors
[[0 0 ] % black
[0 0 ] % white
[0.00 1.0] % red
[0.37 1.0] % green
[0.60 1.0] % blue
[0.50 1.0] % cyan
[0.83 1.0] % magenta
[0.16 1.0] % comment / yellow
] def
/BEGINBITMAPCOLOR {
BITMAPCOLOR} def
/BEGINBITMAPCOLORc {
BITMAPCOLORc} def
/BEGINBITMAPTRUECOLOR {
BITMAPTRUECOLOR } def
/BEGINBITMAPTRUECOLORc {
BITMAPTRUECOLORc } def
/K {
Colors exch get dup
0 get /HUE exch store
1 get /BRIGHT exch store
HUE 0 eq BRIGHT 0 eq and
{1.0 SAT sub setgray}
{HUE SAT BRIGHT sethsbcolor}
ifelse
} def
/FMsetgray {
/SAT exch 1.0 exch sub store
HUE 0 eq BRIGHT 0 eq and
{1.0 SAT sub setgray}
{HUE SAT BRIGHT sethsbcolor}
ifelse
} bind def
}
{
/BEGINBITMAPCOLOR {
BITMAPGRAY} def
/BEGINBITMAPCOLORc {
BITMAPGRAYc} def
/BEGINBITMAPTRUECOLOR {
BITMAPTRUEGRAY } def
/BEGINBITMAPTRUECOLORc {
BITMAPTRUEGRAYc } def
/FMsetgray {setgray} bind def
/K {
pop
} def
}
ifelse
/normalize {
transform round exch round exch itransform
} bind def
/dnormalize {
dtransform round exch round exch idtransform
} bind def
/lnormalize {
0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop
} bind def
/H {
lnormalize setlinewidth
} bind def
/Z {
setlinecap
} bind def
/fillvals FMLOCAL
/X {
fillvals exch get
dup type /stringtype eq
{8 1 setpattern}
{grayness}
ifelse
} bind def
/V {
gsave eofill grestore
} bind def
/N {
stroke
} bind def
/M {newpath moveto} bind def
/E {lineto} bind def
/D {curveto} bind def
/O {closepath} bind def
/n FMLOCAL
/L {
/n exch def
newpath
normalize
moveto
2 1 n {pop normalize lineto} for
} bind def
/Y {
L
closepath
} bind def
/x1 FMLOCAL
/x2 FMLOCAL
/y1 FMLOCAL
/y2 FMLOCAL
/rad FMLOCAL
/R {
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
x1 y1
x2 y1
x2 y2
x1 y2
4 Y
} bind def
% The following commented out code did not work for tangent lines of zero
% length. The code following it was provided by Frame to patch this error.
%
%/RR {
% /rad exch def
% normalize
% /y2 exch def
% /x2 exch def
% normalize
% /y1 exch def
% /x1 exch def
% newpath
% x1 y1 rad add moveto
% x1 y2 x2 y2 rad arcto
% x2 y2 x2 y1 rad arcto
% x2 y1 x1 y1 rad arcto
% x1 y1 x1 y2 rad arcto
% closepath
% 16 {pop} repeat
% } bind def
/rarc
{rad
{arcto} stopped
} bind def
/RR {
/rad exch def
normalize
/y2 exch def
/x2 exch def
normalize
/y1 exch def
/x1 exch def
mark
newpath
x1 y1 rad add moveto
x1 y2 x2 y2 rarc
x2 y2 x2 y1 rarc
x2 y1 x1 y1 rarc
% x2 y1 x1 y1 rarc
x1 y1 x1 y2 rarc
closepath
cleartomark
} bind def
/C {
grestore
gsave
R
clip
} bind def
/FMpointsize FMLOCAL
/F {
FMfonts exch get
FMpointsize scalefont
setfont
} bind def
/Q {
/FMpointsize exch def
F
} bind def
/T {
moveto show
} bind def
/RF {
rotate
0 ne {-1 1 scale} if
} bind def
/TF {
gsave
moveto
RF
show
grestore
} bind def
/P {
moveto
0 32 3 2 roll widthshow
} bind def
/PF {
gsave
moveto
RF
0 32 3 2 roll widthshow
grestore
} bind def
/S {
moveto
0 exch ashow
} bind def
/SF {
gsave
moveto
RF
0 exch ashow
grestore
} bind def
/B {
moveto
0 32 4 2 roll 0 exch awidthshow
} bind def
/BF {
gsave
moveto
RF
0 32 4 2 roll 0 exch awidthshow
grestore
} bind def
/G {
gsave
newpath
normalize translate 0.0 0.0 moveto
dnormalize scale
0.0 0.0 1.0 5 3 roll arc
closepath fill
grestore
} bind def
/A {
gsave
savematrix
newpath
2 index 2 div add exch 3 index 2 div sub exch
normalize 2 index 2 div sub exch 3 index 2 div add exch
translate
scale
0.0 0.0 1.0 5 3 roll arc
restorematrix
stroke
grestore
} bind def
/x FMLOCAL
/y FMLOCAL
/w FMLOCAL
/h FMLOCAL
/xx FMLOCAL
/yy FMLOCAL
/ww FMLOCAL
/hh FMLOCAL
/FMsaveobject FMLOCAL
/FMoptop FMLOCAL
/FMdicttop FMLOCAL
/BEGINPRINTCODE {
/FMdicttop countdictstack 1 add def
/FMoptop count 4 sub def
/FMsaveobject save def
userdict begin
/showpage {} def
FMNORMALIZEGRAPHICS
3 index neg 3 index neg translate
} bind def
/ENDPRINTCODE {
count -1 FMoptop {pop pop} for
countdictstack -1 FMdicttop {pop end} for
FMsaveobject restore
} bind def
/gn {
0
{ 46 mul
cf read pop
32 sub
dup 46 lt {exit} if
46 sub add
} loop
add
} bind def
/str FMLOCAL
/cfs {
/str sl string def
0 1 sl 1 sub {str exch val put} for
str def
} bind def
/ic [
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
0
{0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx}
{10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx}
{19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12}
{13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh}
{4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh}
{13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl}
{7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl}
{0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl}
{10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl}
] def
/sl FMLOCAL
/val FMLOCAL
/ws FMLOCAL
/im FMLOCAL
/bs FMLOCAL
/cs FMLOCAL
/len FMLOCAL
/pos FMLOCAL
/ms {
/sl exch def
/val 255 def
/ws cfs
/im cfs
/val 0 def
/bs cfs
/cs cfs
} bind def
400 ms
/cip {
is
0
cf cs readline pop
{ ic exch get exec
add
} forall
pop
/tot w 1 sub def
0 1 tot {
/indx exch def
/indxa is indx get def
/placer nredt indxa get def
/placeg ngreent indxa get def
/placeb nbluet indxa get def
cris indx placer 255 mul cvi put
cgis indx placeg 255 mul cvi put
cbis indx placeb 255 mul cvi put
} for pop cris
} bind def
/ip {
is
0
cf cs readline pop
{ ic exch get exec
add
} forall
pop
} bind def
/wh {
/len exch def
/pos exch def
ws 0 len getinterval im pos len getinterval copy pop
pos len
} bind def
/bl {
/len exch def
/pos exch def
bs 0 len getinterval im pos len getinterval copy pop
pos len
} bind def
/s1 1 string def
/fl {
/len exch def
/pos exch def
/val cf s1 readhexstring pop 0 get def
pos 1 pos len add 1 sub {im exch val put} for
pos len
} bind def
/hx {
3 copy getinterval
cf exch readhexstring pop pop
} bind def
/h FMLOCAL
/w FMLOCAL
/d FMLOCAL
/lb FMLOCAL
/bitmapsave FMLOCAL
/is FMLOCAL
/cf FMLOCAL
/wbytes {
dup
8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse
} bind def
/BEGINBITMAPBWc {
1 {} COMMONBITMAPc
} bind def
/BEGINBITMAPGRAYc {
8 {} COMMONBITMAPc
} bind def
/BEGINBITMAP2BITc {
2 {} COMMONBITMAPc
} bind def
/COMMONBITMAPc {
/r exch def
/d exch def
gsave
translate rotate scale /h exch def /w exch def
/lb w d wbytes def
sl lb lt {lb ms} if
/bitmapsave save def
r
/is im 0 lb getinterval def
ws 0 lb getinterval is copy pop
/cf currentfile def
w h d [w 0 0 h neg 0 h]
{ip} image
bitmapsave restore
grestore
} bind def
/BEGINBITMAPBW {
1 {} COMMONBITMAP
} bind def
/BEGINBITMAPGRAY {
8 {} COMMONBITMAP
} bind def
/BEGINBITMAP2BIT {
2 {} COMMONBITMAP
} bind def
/COMMONBITMAP {
/r exch def
/d exch def
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
r
/is w d wbytes string def
/cf currentfile def
w h d [w 0 0 h neg 0 h]
{cf is readhexstring pop} image
bitmapsave restore
grestore
} bind def
/proc1 FMLOCAL
/proc2 FMLOCAL
/newproc FMLOCAL
/Fmcc {
/proc2 exch cvlit def
/proc1 exch cvlit def
/newproc proc1 length proc2 length add array def
newproc 0 proc1 putinterval
newproc proc1 length proc2 putinterval
newproc cvx
} bind def
/ngrayt 256 array def
/nredt 256 array def
/nbluet 256 array def
/ngreent 256 array def
/gryt FMLOCAL
/blut FMLOCAL
/grnt FMLOCAL
/redt FMLOCAL
/indx FMLOCAL
/cynu FMLOCAL
/magu FMLOCAL
/yelu FMLOCAL
/k FMLOCAL
/u FMLOCAL
/colorsetup {
currentcolortransfer
/gryt exch def
/blut exch def
/grnt exch def
/redt exch def
0 1 255 {
/indx exch def
/cynu 1 red indx get 255 div sub def
/magu 1 green indx get 255 div sub def
/yelu 1 blue indx get 255 div sub def
/k cynu magu min yelu min def
nredt indx 1 0 cynu max sub redt exec put
ngreent indx 1 0 magu max sub grnt exec put
nbluet indx 1 0 yelu max sub blut exec put
ngrayt indx 1 k sub gryt exec put
} for
} bind def
/tran FMLOCAL
/fakecolorsetup {
/tran 256 string def
0 1 255 {/indx exch def
tran indx
red indx get 77 mul
green indx get 151 mul
blue indx get 28 mul
add add 256 idiv put} for
currenttransfer
{255 mul cvi tran exch get 255.0 div}
exch Fmcc settransfer
} bind def
/BITMAPCOLOR {
/d 8 def
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
colorsetup
/is w d wbytes string def
/ris w d wbytes string def
/gis w d wbytes string def
/bis w d wbytes string def
/cf currentfile def
w h d [w 0 0 h neg 0 h]
{cf is readhexstring pop
/tot w 1 sub def
0 1 tot {
/indx exch def
/indxa is indx get def
/placer nredt indxa get def
/placeg ngreent indxa get def
/placeb nbluet indxa get def
ris indx placer 255 mul cvi put
gis indx placeg 255 mul cvi put
bis indx placeb 255 mul cvi put
} for pop ris}
{gis} {bis} true 3 colorimage
bitmapsave restore
grestore
} bind def
/BITMAPCOLORc {
/d 8 def
gsave
translate rotate scale /h exch def /w exch def
/lb w d wbytes def
sl lb lt {lb ms} if
/bitmapsave save def
colorsetup
/is im 0 lb getinterval def
/cris lb string def
/cgis lb string def
/cbis lb string def
ws 0 lb getinterval is copy pop
/cf currentfile def
w h d [w 0 0 h neg 0 h]
{cip} {cgis} {cbis} true 3 colorimage
bitmapsave restore
grestore
} bind def
/BITMAPTRUECOLORc {
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
/is w string def
ws 0 w getinterval is copy pop
/cf currentfile def
w h 8 [w 0 0 h neg 0 h]
{ip} {gip} {bip} true 3 colorimage
bitmapsave restore
grestore
} bind def
/BITMAPTRUECOLOR {
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
/is w string def
/gis w string def
/bis w string def
/cf currentfile def
w h 8 [w 0 0 h neg 0 h]
{ cf is readhexstring pop }
{ cf gis readhexstring pop }
{ cf bis readhexstring pop }
true 3 colorimage
bitmapsave restore
grestore
} bind def
/BITMAPTRUEGRAYc {
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
/is w string def
ws 0 w getinterval is copy pop
/cf currentfile def
w h 8 [w 0 0 h neg 0 h]
{ip gip bip w gray} image
bitmapsave restore
grestore
} bind def
/ww FMLOCAL
/r FMLOCAL
/g FMLOCAL
/b FMLOCAL
/i FMLOCAL
/gray {
/ww exch def
/b exch def
/g exch def
/r exch def
0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul
b i get .114 mul add add r i 3 -1 roll floor cvi put } for
r
} bind def
/BITMAPTRUEGRAY {
gsave
translate rotate scale /h exch def /w exch def
/bitmapsave save def
/is w string def
/gis w string def
/bis w string def
/cf currentfile def
w h 8 [w 0 0 h neg 0 h]
{ cf is readhexstring pop
cf gis readhexstring pop
cf bis readhexstring pop w gray} image
bitmapsave restore
grestore
} bind def
/BITMAPGRAY {
8 {fakecolorsetup} COMMONBITMAP
} bind def
/BITMAPGRAYc {
8 {fakecolorsetup} COMMONBITMAPc
} bind def
/ENDBITMAP {
} bind def
end
/ALDsave FMLOCAL
/ALDmatrix matrix def ALDmatrix currentmatrix pop
/StartALD {
/ALDsave save def
savematrix
ALDmatrix setmatrix
} bind def
/InALD {
restorematrix
} bind def
/DoneALD {
ALDsave restore
} bind def
%%EndProlog
%%BeginSetup
(3.0) FMVERSION
1 1 612 792 0 1 9 FMDOCUMENT
0 0 /Palatino-Roman FMFONTDEFINE
1 0 /Times-Roman FMFONTDEFINE
2 0 /Times-Bold FMFONTDEFINE
3 0 /Courier FMFONTDEFINE
4 0 /Courier-Bold FMFONTDEFINE
32 FMFILLS
0 0 FMFILL
1 0.1 FMFILL
2 0.3 FMFILL
3 0.5 FMFILL
4 0.7 FMFILL
5 0.9 FMFILL
6 0.97 FMFILL
7 1 FMFILL
8 <0f1e3c78f0e1c387> FMFILL
9 <0f87c3e1f0783c1e> FMFILL
10 <cccccccccccccccc> FMFILL
11 <ffff0000ffff0000> FMFILL
12 <8142241818244281> FMFILL
13 <03060c183060c081> FMFILL
14 <8040201008040201> FMFILL
16 1 FMFILL
17 0.9 FMFILL
18 0.7 FMFILL
19 0.5 FMFILL
20 0.3 FMFILL
21 0.1 FMFILL
22 0.03 FMFILL
23 0 FMFILL
24 <f0e1c3870f1e3c78> FMFILL
25 <f0783c1e0f87c3e1> FMFILL
26 <3333333333333333> FMFILL
27 <0000ffff0000ffff> FMFILL
28 <7ebddbe7e7dbbd7e> FMFILL
29 <fcf9f3e7cf9f3f7e> FMFILL
30 <7fbfdfeff7fbfdfe> FMFILL
%%EndSetup
%%Page: "1" 1
%%BeginPaperSize: Letter
%%EndPaperSize
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(1) 500 42.62 T
1 24 Q
(xFS In-core Inode Management) 153.12 704 T
2 12 Q
(Adam Sweeney) 266.86 664 T
2 16 Q
(1.0 Intr) 72 621.33 T
(oduction) 127.23 621.33 T
1 12 Q
(This document describes the creation, manipulation, and destruction of in-core inodes in xFS. It) 72 594 T
(does not deal with the management of on-disk inodes. It explains in-core inode allocation, lock-) 72 580 T
-0.08 (ing, transactional update, and \336eld management. All of this is subject to change, but this is where) 72 566 P
(things stand at this time.) 72 552 T
2 16 Q
(2.0 Inode Data Structur) 72 511.33 T
(e) 238.28 511.33 T
1 12 Q
(The xFS in-core inode structure is de\336ned as:) 72 484 T
3 9 Q
(typedef struct xfs_inode {) 72 466 T
(struct xfs_ihash) 90 455 T
(*i_hash;) 216 455 T
(/* pointer to hash header */) 360 455 T
(struct xfs_inode) 90 444 T
(*i_next;) 216 444 T
(/* inode hash link forw */) 360 444 T
(struct xfs_inode) 90 433 T
(**i_prevp;) 216 433 T
(/* ptr to prev i_next */) 360 433 T
(struct xfs_mount) 90 422 T
(*i_mount;) 216 422 T
(/* fs mount struct ptr */) 360 422 T
(struct xfs_inode) 90 411 T
(*i_mnext;) 216 411 T
(/* next inode in mount\325s list */) 360 411 T
(struct xfs_inode) 90 400 T
(**i_mprevp;) 216 400 T
(/* ptr to prev i_mnext */) 360 400 T
(struct vnode) 90 389 T
(*i_vnode;) 216 389 T
(/* ptr to associated vnode */) 360 389 T
(dev_t) 90 378 T
(i_dev;) 216 378 T
(/* dev containing this inode */) 360 378 T
(xfs_ino_t) 90 367 T
(i_ino;) 216 367 T
(/* inode number \050agno/agino\051 */) 360 367 T
(xfs_agblock_t) 90 356 T
(i_bno;) 216 356 T
(/* ag block # of inode */) 360 356 T
(int) 90 345 T
(i_index;) 216 345 T
(/* which inode in block */) 360 345 T
(xfs_trans_t) 90 334 T
(*i_transp;) 216 334 T
(/* ptr to owning transaction */) 360 334 T
(xfs_inode_log_item_t) 90 323 T
(i_item;) 216 323 T
(/* logging information */) 360 323 T
(mrlock_t) 90 312 T
(i_lock;) 216 312 T
(/* inode lock */) 360 312 T
(sema_t) 90 301 T
(i_f) 216 301 T
(lock;) 232.18 301 T
(/* inode f) 360 301 T
(lush lock */) 413.92 301 T
(unsigned int) 90 290 T
(i_pincount;) 216 290 T
(/* # of times inode is pinned */) 360 290 T
(sema_t) 90 279 T
(i_pinsema;) 216 279 T
(/* inode pin sema */) 360 279 T
(ushort) 90 268 T
(i_f) 216 268 T
(lags;) 232.18 268 T
(/* misc state */) 360 268 T
(ulong) 90 257 T
(i_vcode;) 216 257 T
(/* version code token \050RFS\051 */) 360 257 T
(ulong) 90 246 T
(i_mapcnt;) 216 246 T
(/* count of mapped pages */) 360 246 T
(ulong) 90 235 T
(i_update_core;) 216 235 T
(/* inode timestamp dirty f) 360 235 T
(lag */) 500.2 235 T
(size_t) 90 224 T
(i_bytes;) 216 224 T
(/* bytes in i_u1 */) 360 224 T
(union {) 90 213 T
(xfs_bmbt_rec_t) 108 202 T
(*iu_extents;) 216 202 T
(/* linear map of f) 360 202 T
(ile extents */) 457.06 202 T
(char) 108 191 T
(*iu_data;) 216 191 T
(/* inline f) 360 191 T
(ile data */) 419.32 191 T
(} i_u1;) 90 180 T
(xfs_btree_block_t) 90 169 T
(*i_broot;) 216 169 T
(/* f) 360 169 T
(ile\325s in-core b-tree root */) 381.57 169 T
(size_t) 90 158 T
(i_broot_bytes;) 216 158 T
(/* bytes allocated for root */) 360 158 T
(union {) 90 147 T
(xfs_bmbt_rec_t) 108 136 T
(iu_inline_ext[2];) 216 136 T
(/* very small f) 360 136 T
(ile extents */) 440.89 136 T
(char) 108 125 T
(iu_inline_data[32];) 216 125 T
(/* very small f) 360 125 T
(ile data */) 440.89 125 T
(dev_t) 108 114 T
(iu_rdev;) 216 114 T
(/* dev number if special */) 360 114 T
(xfs_uuid_t) 108 103 T
(iu_uuid;) 216 103 T
(/* mount point value */) 360 103 T
(} i_u2;) 90 92 T
(ushort) 90 81 T
(i_abytes;) 216 81 T
(/* bytes in i_u3 */) 360 81 T
(union {) 90 70 T
FMENDPAGE
%%EndPage: "1" 2
%%Page: "2" 2
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(2) 500 42.62 T
3 9 Q
(xfs_bmbt_rec_t) 108 714 T
(*iu_aextents;) 216 714 T
(/* map of attribute extents */) 360 714 T
(char) 108 703 T
(*iu_adata;) 216 703 T
(/* inline attribute data */) 360 703 T
(} i_u3;) 90 692 T
(xs_dinode_core_t) 90 681 T
(i_d;) 216 681 T
(/* most of the on-disk inode */) 360 681 T
(} xfs_inode_t;) 72 670 T
2 16 Q
(3.0 Inode Life Cycle) 72 631.33 T
1 12 Q
-0.4 (This section sketches the life cycle of an in-core inode. It follows the inode from the time it is read) 72 604 P
(in from the disk until the time the in-core structure is returned to the kernel heap.) 72 590 T
2 F
(Step 1 Allocate an in-cor) 72 564 T
(e inode) 197.7 564 T
1 F
-0.31 (The \336rst thing the user of in-core inodes needs to do is to get hold of one. This is done via a call to) 72 538 P
(xfs_iget\050\051 or xfs_trans_iget\050\051. The caller speci\336es the inode number of the desired inode and) 72 524 T
-0.33 (whether the inode should be locked exclusively or shared, and the function returns a pointer to the) 72 510 P
(initialized in-core inode. This is usually done as part of \336le lookup. The inode is returned locked) 72 496 T
(with the reference count of the inode\325) 72 482 T
(s vnode incremented. Others may have references to the) 251.85 482 T
(same inode, and the inode lock is used to synchronize accesses to the structure.) 72 468 T
2 F
(Step 2 Look at the inode) 72 442 T
1 F
(Once a process gets a hold of an inode it looks at it. If the process intends to modify the inode it) 72 416 T
(should be locked exclusively) 72 402 T
(, but if it is only reading the inode it should be locked shared. Actu-) 210.13 402 T
-0.13 (ally) 72 388 P
-0.13 (, since inodes are usually found by the lookupname\050\051 routine, their user usually gets the inode/) 89.21 388 P
(vnode with a reference but without a lock. The user then explicitly locks the inode with a call to) 72 374 T
(xfs_ilock\050\051. Once the inode is locked, the process holding it can read any of its \336elds. The inode) 72 360 T
(can only be modi\336ed, however) 72 346 T
(, if it has been brought into the context of a transaction.) 219.75 346 T
2 F
(Step 3 Modifying the inode) 72 320 T
1 F
(If the inode is to be modi\336ed it must be locked exclusively) 72 294 T
(. If the caller did not obtain the inode) 352.72 294 T
(with a call to xfs_trans_iget\050\051, which is just like xfs_iget\050\051 except that it takes a transaction) 72 280 T
-0.31 (pointer) 72 266 P
-0.31 (, then it should be locked exclusively with a call to xfs_ilock\050\051 and added to the transaction) 105.5 266 P
(with a call to xfs_trans_ijoin\050\051. Once this is done the inode can be modi\336ed. When all changes to) 72 252 T
(the inode have been made, the transaction mechanism needs to be told what within the inode has) 72 238 T
(been changed and therefore needs to be logged.) 72 224 T
2 F
(Step 4 Logging the inode changes) 72 198 T
1 F
(The changes made to an inode can be logged as part of a transaction using the xfs_trans_log_in-) 72 172 T
(ode\050\051 function. This function takes \337ags indicating which parts of the inode have been modi\336ed) 72 158 T
(and therefore need to be logged. These \337ags are all de\336ned in xfs_inode_item.h and will be) 72 144 T
(described in more detail later on.) 72 130 T
2 F
(Step 5 Releasing the inode) 72 104 T
FMENDPAGE
%%EndPage: "2" 3
%%Page: "3" 3
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(3) 500 42.62 T
1 12 Q
(Once a process is through looking at an inode or modifying an inode, the inode needs to be) 72 712 T
-0.2 (unlocked and released. If the inode was not used as part of a transaction, then the process can sim-) 72 698 P
(ply call xfs_iput\050\051 which will unlock the inode and release the reference to the inode\325) 72 684 T
(s vnode. If) 479.69 684 T
(the inode is being used as part of a transaction, then when the process calls xfs_trans_commit\050\051) 72 670 T
(the inode will be unlocked and its reference released. If the process wants to hold onto the inode) 72 656 T
(even after the commit, then it needs to call xfs_trans_ihold\050\051 before committing the transaction.) 72 642 T
(This tells the transaction code not to unlock or release the inode when the transaction commits.) 72 628 T
2 F
(Step 6 W) 72 602 T
(riting back inode changes) 118.43 602 T
1 F
(When an inode is modi\336ed as part of a transaction, the dirty inode structure will remain in mem-) 72 576 T
(ory and the changes will be written into the on-disk log. At some point the inode will be written) 72 562 T
(back to its on-disk home by either bd\337ush\050\051 calling xfs_sync\050\051 or by the inode structure being) 72 548 T
(reclaimed for use as another inode. In either case, all modi\336cations to the inode will at this point) 72 534 T
(be written back to the disk and the on-disk log copy will no longer be needed for \336le system) 72 520 T
(recovery) 72 506 T
(.) 113.17 506 T
2 F
(Step 7 Destr) 72 480 T
(oying the inode structur) 134.4 480 T
(e) 257.12 480 T
1 F
(As mentioned above, the inode structure may at some point be recycled for use as another inode.) 72 454 T
(This is the end of the in-core inode\325) 72 440 T
(s life cycle as its memory is freed and reused for something) 242.88 440 T
(else.) 72 426 T
2 16 Q
(4.0 Inode Allocation) 72 385.33 T
1 12 Q
(In-core inodes are allocated by calls to xfs_iget\050\051. The function prototype for xfs_iget\050\051 is:) 72 358 T
3 9 Q
(xfs_inode_t) 90 340 T
(*xfs_iget\050xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint f) 149.32 340 T
(lags\051.) 499.83 340 T
1 12 Q
(The caller gives a pointer to the \336le system\325) 72 316 T
(s mount structure, a transaction pointer if executing) 281.86 316 T
-0.4 (within a transaction, the inode number of the desired inode, and \337ags indicating whether the inode) 72 302 P
(should be locked in shared or exclusive mode. The function returns a pointer to the in-core ver-) 72 288 T
(sion of the desired inode. The inode is returned to the caller locked in the requested mode. The) 72 274 T
(\336elds of the inode will be \336lled in according to the format of the on-disk inode.) 72 260 T
-0.39 (If the inode is in LOCAL format, meaning that the \336le\325) 72 234 P
-0.39 (s data \336ts entirely within the on-disk inode,) 332.25 234 P
(then i_u1.iu_data will point to an in memory array containing the contents of the \336le and i_bytes) 72 220 T
(will contain the number of bytes in the array) 72 206 T
(. This array will either be the i_u2.iu_inline_data) 284.4 206 T
-0.26 (array if the \336le data is less than or equal to 32 bytes or it will be an array allocated from the kernel) 72 192 P
(heap. If the \336le is of length 0, then i_u1.iu_data will be NULL and i_bytes will be 0.) 72 178 T
(If the inode is in EXTENTS format, meaning that the \336le\325) 72 152 T
(s data will not \336t in the on-disk inode) 349.49 152 T
-0.24 (but the extent descriptors for the inode will, then i_u1.iu_extents will point to an in memory array) 72 138 P
(containing the extent descriptors of the \336le and i_bytes will contain the number of bytes in the) 72 124 T
-0.38 (array) 72 110 P
-0.38 (. This array will be either the i_u1.iu_inline_ext array if there are only 1 or 2 extents or it will) 95.86 110 P
(be an array allocated from the kernel heap. If the \336le is of length 0, then i_u1.iu_extents will be) 72 96 T
(NULL and i_bytes will be 0. The XFS_IEXTENTS \337ag will be set in i_\337ags. This \337ag indicates) 72 82 T
(that all of the \336le\325) 72 68 T
(s extent descriptors have been read in and are in the i_u1.iu_extents array) 157.29 68 T
(.) 508.56 68 T
FMENDPAGE
%%EndPage: "3" 4
%%Page: "4" 4
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(4) 500 42.62 T
1 12 Q
(If the inode is in BTREE format, meaning that the \336le has too many extent descriptors to \336t into) 72 712 T
-0.14 (the on-disk inode, then i_broot will point to an in memory array containing the \336le\325) 72 698 P
-0.14 (s extent b-tree) 469.48 698 P
(root and i_broot_bytes will contain the number of bytes in the array) 72 684 T
(. If the XFS_IEXTENTS \337ag) 396 684 T
(is set in i_\337ags, then i_u1.iu_extents will point to an array containing all of the extents of the \336le) 72 670 T
-0.12 (as in the case above. If the \337ag is not set, then the extents have not yet been read in and should be) 72 656 P
(read in with a call to xfs_ireadindir\050\051 if they are needed. Lazily reading in all of the extents for) 72 642 T
(\336les with a lar) 72 628 T
(ge number of extents ensures that simple stat\050\051s of the \336le can be done ef) 140.07 628 T
(\336ciently) 489.6 628 T
(.) 528.13 628 T
(The returned inode will be hashed into a per \336le system in-core inode hash table. W) 72 602 T
(e are switch-) 472.75 602 T
(ing from the traditional single hash table for all \336le systems to per \336le system hash tables to) 72 588 T
(improve the scalability of the system. Calls to xfs_iget\050\051 \336rst look for the desired inode in this) 72 574 T
-0.33 (hash table before bringing in the inode from disk. An in-core inode is only removed from the hash) 72 560 P
-0.44 (table when it is recycled. The inode will also be placed on a list attached to the \336le system\325) 72 546 P
-0.44 (s mount) 499.55 546 P
(structure. This list is used for traversal of all the in-core inodes in routines such as xfs_sync\050\051.) 72 532 T
2 16 Q
(5.0 Inode in-line data/extents/b-tr) 72 491.33 T
(ee r) 304.03 491.33 T
(oot) 329.04 491.33 T
1 12 Q
-0.05 (This section describes the management of the iu_data, iu_extents, and i_broot \336elds. These \336elds) 72 464 P
(point to arrays whose size must change as the size of the \336le changes.) 72 450 T
2 14 Q
(5.1 iu_data) 72 416.67 T
1 12 Q
(As described in the section on inode allocation, this \336eld points to an array containing the in-line) 72 390 T
(data of an inode in LOCAL format. When the size of a \336le in this format changes, the process) 72 376 T
(changing the size should call xfs_idata_realloc\050\051 to resize the in-core array) 72 362 T
(. This function takes) 428.92 362 T
(the delta in the number of bytes needed. If the delta is positive then more memory will be allo-) 72 348 T
(cated for the array) 72 334 T
(, and if it is negative the array will be made smaller) 158.8 334 T
(. If the size goes to 0 then) 404.62 334 T
-0.35 (iu_data will be made NULL. If the size is to become greater than will \336t in the on-disk inode, then) 72 320 P
(it is the responsibility of the process changing the size to perform a transaction to change the) 72 306 T
(inode from LOCAL to EXTENTS format. As a part of that transaction the in-line data should be) 72 292 T
(logged, the iu_data array should be freed with a call to xfs_idata_realloc\050\051, and an array for the) 72 278 T
(inode\325) 72 264 T
(s extents should be allocated in iu_extents with a call to xfs_iext_realloc\050\051.) 101.98 264 T
2 14 Q
(5.2 iu_extents) 72 230.67 T
1 12 Q
(When an inode is in EXTENTS or BTREE format, this \336eld points to an array containing all of) 72 204 T
(the extent descriptors for that inode. If the \336le is in EXTENTS format, then this array is guaran-) 72 190 T
-0.09 (teed to be there unless the \336le is of length 0. If the \336le is in BTREE format, then this array is read) 72 176 P
(in when it is \336rst needed and its presence is signi\336ed by the XFS_IEXTENTS \337ag in the inode\325) 72 162 T
(s) 529.39 162 T
(i_\337ags \336eld. When the number of extents in the \336le changes, the process changing the number of) 72 148 T
(extents should call xfs_iext_realloc\050\051 to resize the in-core array) 72 134 T
(. This function takes the delta in) 374.31 134 T
-0.42 (the number of extents needed. It allocates and frees memory for the array as needed. If the number) 72 120 P
(of extents goes to 0 then iu_extents will be set to NULL. If the number of extents exceeds some) 72 106 T
(threshold which is yet to be determined, then the array will stop growing and the block mapping) 72 92 T
(code will have to do slower access through its b-tree in the buf) 72 78 T
(fer cache.) 372.23 78 T
FMENDPAGE
%%EndPage: "4" 5
%%Page: "5" 5
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(5) 500 42.62 T
1 12 Q
-0.22 (The iu_extents array contains all of the extents of the inode sorted by \336le of) 72 712 P
-0.22 (fset. It will be used by) 431.74 712 P
(the block mapping code to quickly \336nd the location of \336le disk blocks. This will be done by) 72 698 T
(binary search of the array) 72 684 T
(, possibly enhanced with a single entry cache for improving the ef) 193.77 684 T
(\336-) 509.99 684 T
(ciency of sequential access lookups.) 72 670 T
2 14 Q
(5.3 iu_br) 72 636.67 T
(oot) 128.89 636.67 T
1 12 Q
(When an inode is in BTREE format, this \336eld points to an in-core copy of the on-disk inode\325) 72 610 T
(s b-) 516.39 610 T
-0.27 (tree root. Like the other arrays mentioned above, this array only takes enough memory to hold the) 72 596 P
(used portion of the b-tree root and must be resized dynamically as the root grows and shrinks.) 72 582 T
(This is done by calls to xfs_iroot_realloc\050\051, which takes the change in the number of b-tree) 72 568 T
-0.27 (records needed. This routine understands the format of the b-tree root, and it moves existing infor-) 72 554 P
(mation within the root as is appropriate when the size changes. This means that when the size of) 72 540 T
(the root increases by some number of records the pointers for the records are shifted towards the) 72 526 T
(end of the data structure, and when the size shrinks the pointers are moved forward.) 72 512 T
(When the number of records in the b-tree root goes to 0, the data structure is not freed because it) 72 486 T
(still contains the b-tree block header) 72 472 T
(. If this is no longer needed, the process should call) 245.54 472 T
(xfs_iroot_free\050\051 to release the memory used to contain the root. This should only be done if the) 72 458 T
(inode is no longer in BTREE format.) 72 444 T
2 14 Q
(5.4 i_bytes and i_br) 72 410.67 T
(oot_bytes) 192.64 410.67 T
1 12 Q
(These two counters track the used bytes in the arrays pointed to by the corresponding iu_data/) 72 384 T
(iu_extents and i_broot \336elds. For now the arrays are exactly the size that is currently needed,) 72 370 T
(except when using the iu_inline_data/iu_inline_ext array) 72 356 T
(. This implies that we must call kmem_-) 344.03 356 T
-0.36 (realloc\050\051 or something similar each time one of the xfs_i***_realloc\050\051 routines is called. W) 72 342 P
-0.36 (e could) 502.74 342 P
-0.33 (keep more memory than we are currently using in an attempt to reduce the number of kmem calls,) 72 328 P
-0.4 (but this is currently being traded in favor of better memory utilization. If this turns out to be a high) 72 314 P
(overhead decision in terms of cpu cycles, we can pretty easily change it.) 72 300 T
2 16 Q
(6.0 Inode locking) 72 259.33 T
1 12 Q
(As mentioned above, inodes can be locked in either shared or exlusive mode. This means we can) 72 232 T
(have multiple readers of the same inode simutaneously) 72 218 T
(. This should allow multiple readers and) 334.7 218 T
(non-allocating writers of the \336le to work in parallel. Simultaneous \336le access is especially impor-) 72 204 T
-0.23 (tant for async I/O and for directories. Our async I/O implementation is based on threads, so allow-) 72 190 P
-0.1 (ing multiple threads to access the \336le at the same time can increase the pipeline of I/O requests to) 72 176 P
(high throughput devices such as lar) 72 162 T
(ge, striped volumes. Directories are read doing path searches) 241.34 162 T
(far more often than they are written, so allowing parallel access to popular directories should) 72 148 T
-0.14 (increase our pathname resolution performance. This has been a signi\336cant bottleneck in other \336le) 72 134 P
(systems, so this should be a big win.) 72 120 T
(The inode lock will need to be held exclusively for anything updating the contents of the inode.) 72 94 T
(The contents includes all \336elds which are contained in the on-disk inode and others as needed.) 72 80 T
FMENDPAGE
%%EndPage: "5" 6
%%Page: "6" 6
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(6) 500 42.62 T
2 16 Q
(7.0 Inode transactions and logging) 72 709.33 T
1 12 Q
(Almost all changes to an inode which will be re\337ected in the on-disk inode must be done within) 72 682 T
(the context of a transaction and must logged within that transaction. The only exceptions to this) 72 668 T
-0.33 (may be the access, change, and modify times on the inode which are discussed in the next section.) 72 654 P
(Once an inode has been modi\336ed, the transaction mechanism should be noti\336ed of the change) 72 640 T
-0.45 (with a call to xfs_trans_log_inode\050\051. This function takes a set of \337ags indicating which parts of the) 72 626 P
(inode have been changed. The \337ags are:) 72 612 T
4 F
(\245) 72 592 T
1 F
-0.28 (XFS_ILOG_MET) 85.75 592 P
-0.28 (A -- This should be speci\336ed if any of the \336elds in the i_d sub-structure have) 172.73 592 P
(been modi\336ed.) 85.75 578 T
4 F
(\245) 72 558 T
1 F
-0.12 (XFS_ILOG_DA) 85.75 558 P
-0.12 (T) 164.36 558 P
-0.12 (A -- This should be speci\336ed if the inline data of the inode has been changed.) 170.73 558 P
4 F
(\245) 72 538 T
1 F
-0.07 (XFS_ILOG_EXT -- This should be speci\336ed if the iu_extents array has been modi\336ed and the) 85.75 538 P
(\336le is in EXTENTS format.) 85.75 524 T
4 F
(\245) 72 504 T
1 F
(XFS_ILOG_BROOT -- This should be speci\336ed if the \336le is in BTREE format and the con-) 85.75 504 T
(tents of the i_broot array have been modi\336ed.) 85.75 490 T
4 F
(\245) 72 470 T
1 F
(XFS_ILOG_DEV -- This should be speci\336ed if the i_u2.iu_rdev \336eld has been modi\336ed.) 85.75 470 T
(These \337ags tell the transaction code which parts of the inode need to be logged when the current) 72 444 T
(transaction commits. Each speci\336ed section is logged in its entirety) 72 430 T
(, so specifying XFS_ILOG_-) 393.69 430 T
-0.43 (MET) 72 416 P
-0.43 (A will log the entire xfs_dinode_core structure embedded in the in-core inode and specifying) 96.36 416 P
(XFS_ILOG_BROOT will log the entire b-tree root. W) 72 402 T
(e will not be logging little, tiny pieces of) 332.87 402 T
(the inode, because the overhead for tracking such pieces is as high as the overhead for copying) 72 388 T
(them into the log.) 72 374 T
-0.37 (When a transaction manipulating an inode commits, the inode is unlocked and the reference to the) 72 348 P
(inode is released. In order to prevent dirty inodes from being reclaimed, which could become a) 72 334 T
(performance problem if they are reclaimed while they are still pinned by a transaction, when a) 72 320 T
(clean inode is logged an additional reference to the inode will be taken by the transaction code.) 72 306 T
(This reference will be released when the inode is \337ushed back to disk to clean it.) 72 292 T
2 16 Q
(8.0 Inode timestamp updates) 72 251.33 T
1 12 Q
-0.13 (The access, modify) 72 224 P
-0.13 (, and change timestamps within the inode are updated on almost every \336le sys-) 163.89 224 P
(tem operation. Requiring the inode to be locked exlusively and updating the timestamps within) 72 210 T
-0.23 (transactions would be overly expensive and would eliminate the bene\336ts we hope to gain in using) 72 196 P
(the multi-reader inode lock. Instead, inode timestamps will be updated outside the protection of) 72 182 T
(even the inode lock.The scheme will work as follows.) 72 168 T
(Whenever a process needs to update a timestamp or timestamps, it will simply store the current) 72 142 T
(time into the timestamps.) 72 128 T
2 F
(After) 196.28 128 T
1 F
( updating the timestamps it will set the i_update_core \336eld in the) 223.57 128 T
-0.35 (inode to 1 to indicate the the inode is dirty) 72 114 P
-0.35 (. This \336eld is only cleared from xfs_i\337ush\050\051, which does) 270.98 114 P
(so) 72 100 T
2 F
(befor) 85.66 100 T
(e) 112.75 100 T
1 F
(copying the timestamps from the in-core inode to the on-disk inode. This ordering of) 121.08 100 T
(the i_update_core updates, given that our machines support a strongly ordered memory model,) 72 86 T
(ensures that we will never miss an update and consider a dirty inode to be clean.) 72 72 T
FMENDPAGE
%%EndPage: "6" 7
%%Page: "7" 7
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(7) 500 42.62 T
1 12 Q
(The timestamp \336elds themselves will be 64 bit \336elds of which we will currently only use the) 72 712 T
(upper 32 bits to store the time in seconds. The other 32 bits will be left unused in case we need) 72 698 T
(\336ner grade timestamps in the future. Since 32 bit stores are atomic, each individual timestamp) 72 684 T
(will be consistent at all times. However) 72 670 T
(, there is no locking around multiple timestamp updates,) 261.06 670 T
-0.14 (so updates to multiple timestamps at once will not be atomic. In the normal case anyone updating) 72 656 P
(the timestamps is putting in the current time so this should not matter) 72 642 T
(, but this is not the case for) 404.01 642 T
-0.12 (the utimes\0502\051 system call. This system call is used to set the timestamps to arbitrary values. Since) 72 628 P
(we will have no locking it will be possible to mix the results of a utimes\0502\051 system call and a nor-) 72 614 T
-0.45 (mal path timestamp update. In the name of performance, since \336xing this would require a lock, we) 72 600 P
(are not going to worry about this.) 72 586 T
2 16 Q
(9.0 Inode \337ushing) 72 545.33 T
1 12 Q
(Dirty inodes are \337ushed to disk either by calls to efs_sync\050\051 from the bd\337ush daemon or by the) 72 518 T
(transaction management code when an inode\325) 72 504 T
(s log image is too far back in the log. The inode) 290.83 504 T
-0.43 (must be locked in shared mode to prevent other processes from modifying the inode but still allow) 72 490 P
(other processes to look at the inode while it is being written to disk. Since multiple processes) 72 476 T
(could attempt to \337ush the inode simultaneously) 72 462 T
(, the i_\337ock will be used to synchronize the \337ush-) 298.44 462 T
(ing of an inode. This is necessary both for performance and for correctness. For performance we) 72 448 T
-0.19 (don\325) 72 434 P
-0.19 (t wan\325) 93.77 434 P
-0.19 (t to do unnecessary work. For correctness we must make sure that the one reference on) 123.67 434 P
-0.37 (the inode taken by the transaction management code is not used or released by multiple processes.) 72 420 P
(Once the reference is released, it will be possible for the inode to be recycled. Thus only one pro-) 72 406 T
(cess can assume that the reference will protect it.) 72 392 T
-0.1 (The routine to perform the actual \337ushing of the inode is xfs_i\337ush\050\051. This routine will obtain the) 72 366 P
(buf) 72 352 T
(fer for the disk block of the inode from the buf) 87.77 352 T
(fer cache, copy the inode into that buf) 311.39 352 T
(fer) 493.03 352 T
(, and) 505.86 352 T
(write the buf) 72 338 T
(fer back to the disk synchronously) 133.07 338 T
(, asynchronously) 297.18 338 T
(, or delayed write. If the inode is) 377.68 338 T
-0.11 (pinned in memory \050because it is a part of a transaction which has not yet been committed to disk\051) 72 324 P
-0.23 (this routine will sleep until it is unpinned. When the inode is not pinned the routine will attach the) 72 310 P
(function xfs_i\337ush_done\050\051 and the inode\325) 72 296 T
(s log item to the buf) 270.54 296 T
(fer) 366.61 296 T
(\325) 380.36 296 T
(s b_iodone function and the) 383.7 296 T
(b_fsprivate pointer) 72 282 T
(.) 162.27 282 T
1 10 Q
(1) 165.27 286.8 T
1 12 Q
(This routine will be executed when the write completes. Its purpose is to) 170.27 282 T
(remove the inode from the \336le system\325) 72 268 T
(s Active Item List, mark the inode clean, and release the) 257.21 268 T
(reference to the inode taken by the transaction code. Finally) 72 254 T
(, the inode will be marked clean,) 358.33 254 T
(unlocked and the buf) 72 240 T
(fer write initiated.) 172.71 240 T
(Since the buf) 72 214 T
(fer is unlocked in xfs_i\337ush\050\051, it is possible for the inode to be dirtied again before) 135.07 214 T
(the write completes and xfs_i\337ush_done\050\051 executes. In this case the inode may even be moved) 72 200 T
(forward in the AIL, meaning that the \337ush being completed by xfs_i\337ush_done\050\051 does not have) 72 186 T
(the right to remove the inode from the AIL. In order to coordinate this, xfs_i\337ush_done\050\051 will do) 72 172 T
(the following:) 72 158 T
72 114 540 134 C
72 122 204 122 2 L
0.25 H
2 Z
0 X
0 K
N
0 0 612 792 C
1 10 Q
0 X
0 K
-0.17 (1. These will be attached using the xfs_buf_attach_iodone\050\051 function. This will chain the inode log item onto a chain) 72 107.33 P
(of log items rooted at the buf) 72 95.33 T
(fer) 187.86 95.33 T
(\325) 199.32 95.33 T
(s b_fsprivate \336eld. This will require the buf log item code to handle having the buf) 202.1 95.33 T
(log item not being pointed to directly by the buf) 72 83.33 T
(\325) 264.38 83.33 T
(s b_fsprivate \336eld. It will get us, however) 267.16 83.33 T
(, a clean, generic mecha-) 433.04 83.33 T
(nism for attaching log item\325) 72 71.33 T
(s to the io completion of buf) 183.05 71.33 T
(fers.) 296.14 71.33 T
FMENDPAGE
%%EndPage: "7" 8
%%Page: "8" 8
612 792 0 FMBEGINPAGE
0 8 Q
0 X
0 K
(Silicon Graphics Pr) 72 750.67 T
(oprietary) 139.57 750.67 T
72 54 540 54 2 L
0.25 H
2 Z
N
(xFS In-cor) 72 42.62 T
(e Inode Management) 107.71 42.62 T
(November 29, 1993) 254.1 42.62 T
(8) 500 42.62 T
4 12 Q
(\245) 72 712 T
1 F
(First look at the inode\325) 85.75 712 T
(s LSN without obtaining the AIL lock \050which protects this \336eld\051. If it) 194.36 712 T
(has changed then the inode has moved or is moving in the AIL and we should not bother with) 85.75 698 T
(it.) 85.75 684 T
4 F
(\245) 72 664 T
1 F
(If the value has not changed then get the AIL lock and if the value has still not changed then) 85.75 664 T
(remove the inode from the AIL.) 85.75 650 T
4 F
(\245) 72 630 T
1 F
(Next, release the inode\325) 85.75 630 T
(s i_\337ock.) 198.99 630 T
4 F
(\245) 72 610 T
1 F
(Finally) 85.75 610 T
(, release the reference to the inode.) 118.96 610 T
-0.21 (Once the reference is released, we can no longer manipulate or look at the inode and we are done.) 72 584 P
-0.05 (Note that we are not doing anything special with the inode reference for the case where the inode) 72 570 P
(is re-dirtied while the disk write is taking place. Since the inode will be marked clean in xfs_i-) 72 556 T
(\337ush\050\051 before releasing the lock, any process modifying the inode during the write will obtain) 72 542 T
(another reference for the transaction code. This allows us to just drop the one that we are using.) 72 528 T
2 16 Q
(10.0 Inode r) 72 487.33 T
(ecycling) 157.89 487.33 T
1 12 Q
-0.07 (At some point a call to xfs_reclaim\050\051 will want to recycle an inode which is not being referenced.) 72 460 P
-0.06 (The inode is guaranteed to have no references at this point, so we know that it is not dirty) 72 446 P
-0.06 (. All we) 498.87 446 P
-0.02 (need to do is \337ush any dirty \336le data associated with the inode, remove the inode from the mount) 72 432 P
(structure\325) 72 418 T
(s list of in-core inodes, and free all memory associated with the inode.) 117.3 418 T
FMENDPAGE
%%EndPage: "8" 9
%%Trailer
%%BoundingBox: 0 0 612 792
%%Pages: 8 1
%%DocumentFonts: Palatino-Roman
%%+ Times-Roman
%%+ Times-Bold
%%+ Courier
%%+ Courier-Bold