Whamcloud - gitweb
current branches now use lnet from HEAD
[fs/lustre-release.git] / lustre / smfs / doc / dld.lyx
1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
2 \lyxformat 221
3 \textclass article
4 \begin_preamble
5 \usepackage{listings}
6 \usepackage[usenames]{color}
7 \usepackage{courier}
8
9 %\usepackage{pt}
10 %\usepackage{units}
11 %\usepackage{coz}
12
13 %\usepackage{epsf}
14 %\usepackage{lncsexample}
15 %\conttrue
16 %\usepackage{times}
17 %\usepackage{top}
18 %\usepackage{graphicx}
19 \newcommand{\lst}[3] {
20         \noindent\vspace{-1mm}
21         \definecolor{cKeyword}{rgb}{0.8,0.1,0.1}
22         \definecolor{cComment}{rgb}{0.2,0.5,0.7}
23         \definecolor{cString}{rgb}{0.2,0.7,0.2}
24         \lstinputlisting[caption={#2},
25         label={#1},
26         showstringspaces=false, 
27         numbers=left, 
28         stepnumber=1,
29         frame=lines,
30         language=C,
31         extendedchars=true,
32         basicstyle=\small\tt,
33         numberstyle=\tiny,
34         keywordstyle=\color{cKeyword},
35         commentstyle=\color{cComment},
36         stringstyle=\color{cString},
37         directivestyle=\color{magenta},
38         emph={1, 2, 3, 4, 5, 6, 7, 8, 9, 0, NULL, lustre, CFS},
39         emphstyle=\color{blue},
40         breaklines=true,
41         #3]{#1}\vspace{0.3mm}
42 }
43 \end_preamble
44 \language english
45 \inputencoding koi8-r
46 \fontscheme times
47 \graphics default
48 \paperfontsize default
49 \spacing single 
50 \papersize Default
51 \paperpackage a4
52 \use_geometry 1
53 \use_amsmath 0
54 \use_natbib 0
55 \use_numerical_citations 0
56 \paperorientation portrait
57 \leftmargin 4cm
58 \topmargin 2cm
59 \rightmargin 2cm
60 \bottommargin 2cm
61 \secnumdepth 3
62 \tocdepth 3
63 \paragraph_separation skip
64 \defskip medskip
65 \quotes_language swedish
66 \quotes_times 2
67 \papercolumns 1
68 \papersides 1
69 \paperpagestyle default
70
71 \layout Title
72
73 SMFS Detailed Level Design
74 \layout Author
75
76 Mike Pershin
77 \layout Date
78
79 21 February 2005
80 \layout Standard
81 \pagebreak_bottom \noindent 
82
83 \begin_inset LatexCommand \tableofcontents{}
84
85 \end_inset 
86
87
88 \layout Section
89
90
91 \noun on 
92 Functional Specification
93 \layout Subsection
94
95 SMFS operations
96 \layout Subsubsection
97
98 Initialization and data structures
99 \layout Standard
100
101 SMFS implement all needed methods as filesystem but uses other filesystem
102  as store instead of block device.
103  This way demands that SMFS should care about this backstore FS like VFS.
104  SMFS defines several info structures for each filesystem object that contain
105  all needed information about backstore related stuff and etc.
106 \layout Subsubsection
107
108 Plugin handling
109 \layout Standard
110
111 SMFS has plugin API which allows to register/deregister plugins and call
112  their functions.
113  Plugins are organized in linked list.
114 \layout Standard
115
116 Plugin initialization starts when smfs is mounting by someone with options
117  that contain information about plugin needed.
118  Deactivated process starts when SMFS unmount occur.
119  It possible to use ioctl interface or procfs (sysfs later) for plugin managemen
120 t.
121  Each plugin will receives notification from SMFS about filesystem operations.
122  Plugins should be aware of delays, transaction handling and consistency.
123 \layout Standard
124
125 SMFS contains information about plugin loaded with special flags.
126  There are system-wide flags and object-related to indicate exclusions.
127 \layout Subsubsection
128
129 Locking and plugins
130 \layout Standard
131
132 Every hook is called under some conditions in term of resource availability.
133  SMFS should provide that all pre- and post-operation stuff should be done
134  together with fs operation in backstore fs.
135  Plugins should be aware about these conditions and acts properly.
136 \layout Subsubsection*
137
138
139 \emph on 
140 Inode_operations
141 \layout Standard
142
143 locking rules: all may block, none have BKL.
144  Protection provided through using i_sem semaphore in inode.
145 \layout Standard
146
147
148 \begin_inset  Tabular
149 <lyxtabular version="3" rows="17" columns="3">
150 <features>
151 <column alignment="center" valignment="top" leftline="true" width="0">
152 <column alignment="center" valignment="top" leftline="true" width="0">
153 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
154 <row topline="true" bottomline="true">
155 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
156 \begin_inset Text
157
158 \layout Standard
159
160 \end_inset 
161 </cell>
162 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
163 \begin_inset Text
164
165 \layout Standard
166
167 i_sem
168 \end_inset 
169 </cell>
170 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
171 \begin_inset Text
172
173 \layout Standard
174
175 Notes
176 \end_inset 
177 </cell>
178 </row>
179 <row topline="true">
180 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
181 \begin_inset Text
182
183 \layout Standard
184
185 lookup
186 \end_inset 
187 </cell>
188 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
189 \begin_inset Text
190
191 \layout Standard
192
193 yes
194 \end_inset 
195 </cell>
196 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
197 \begin_inset Text
198
199 \layout Standard
200
201 \end_inset 
202 </cell>
203 </row>
204 <row topline="true">
205 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
206 \begin_inset Text
207
208 \layout Standard
209
210 create
211 \end_inset 
212 </cell>
213 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
214 \begin_inset Text
215
216 \layout Standard
217
218 yes
219 \end_inset 
220 </cell>
221 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
222 \begin_inset Text
223
224 \layout Standard
225
226 \end_inset 
227 </cell>
228 </row>
229 <row topline="true">
230 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
231 \begin_inset Text
232
233 \layout Standard
234
235 link
236 \end_inset 
237 </cell>
238 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
239 \begin_inset Text
240
241 \layout Standard
242
243 yes
244 \end_inset 
245 </cell>
246 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
247 \begin_inset Text
248
249 \layout Standard
250
251 both
252 \end_inset 
253 </cell>
254 </row>
255 <row topline="true">
256 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
257 \begin_inset Text
258
259 \layout Standard
260
261 mknod
262 \end_inset 
263 </cell>
264 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
265 \begin_inset Text
266
267 \layout Standard
268
269 yes
270 \end_inset 
271 </cell>
272 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
273 \begin_inset Text
274
275 \layout Standard
276
277 \end_inset 
278 </cell>
279 </row>
280 <row topline="true">
281 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
282 \begin_inset Text
283
284 \layout Standard
285
286 symlink
287 \end_inset 
288 </cell>
289 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
290 \begin_inset Text
291
292 \layout Standard
293
294 yes
295 \end_inset 
296 </cell>
297 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
298 \begin_inset Text
299
300 \layout Standard
301
302 \end_inset 
303 </cell>
304 </row>
305 <row topline="true">
306 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
307 \begin_inset Text
308
309 \layout Standard
310
311 mkdir
312 \end_inset 
313 </cell>
314 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
315 \begin_inset Text
316
317 \layout Standard
318
319 yes
320 \end_inset 
321 </cell>
322 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
323 \begin_inset Text
324
325 \layout Standard
326
327 \end_inset 
328 </cell>
329 </row>
330 <row topline="true">
331 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
332 \begin_inset Text
333
334 \layout Standard
335
336 unlink
337 \end_inset 
338 </cell>
339 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
340 \begin_inset Text
341
342 \layout Standard
343
344 yes
345 \end_inset 
346 </cell>
347 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
348 \begin_inset Text
349
350 \layout Standard
351
352 both
353 \end_inset 
354 </cell>
355 </row>
356 <row topline="true">
357 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
358 \begin_inset Text
359
360 \layout Standard
361
362 rmdir
363 \end_inset 
364 </cell>
365 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
366 \begin_inset Text
367
368 \layout Standard
369
370 yes
371 \end_inset 
372 </cell>
373 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
374 \begin_inset Text
375
376 \layout Standard
377
378 both
379 \end_inset 
380 </cell>
381 </row>
382 <row topline="true">
383 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
384 \begin_inset Text
385
386 \layout Standard
387
388 rename
389 \end_inset 
390 </cell>
391 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
392 \begin_inset Text
393
394 \layout Standard
395
396 yes
397 \end_inset 
398 </cell>
399 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
400 \begin_inset Text
401
402 \layout Standard
403
404 all
405 \end_inset 
406 </cell>
407 </row>
408 <row topline="true">
409 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
410 \begin_inset Text
411
412 \layout Standard
413
414 truncate
415 \end_inset 
416 </cell>
417 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
418 \begin_inset Text
419
420 \layout Standard
421
422 yes
423 \end_inset 
424 </cell>
425 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
426 \begin_inset Text
427
428 \layout Standard
429
430 \end_inset 
431 </cell>
432 </row>
433 <row topline="true">
434 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
435 \begin_inset Text
436
437 \layout Standard
438
439 setattr
440 \end_inset 
441 </cell>
442 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
443 \begin_inset Text
444
445 \layout Standard
446
447 yes
448 \end_inset 
449 </cell>
450 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
451 \begin_inset Text
452
453 \layout Standard
454
455 \end_inset 
456 </cell>
457 </row>
458 <row topline="true">
459 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
460 \begin_inset Text
461
462 \layout Standard
463
464 getattr
465 \end_inset 
466 </cell>
467 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
468 \begin_inset Text
469
470 \layout Standard
471
472 no
473 \end_inset 
474 </cell>
475 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
476 \begin_inset Text
477
478 \layout Standard
479
480 \end_inset 
481 </cell>
482 </row>
483 <row topline="true">
484 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
485 \begin_inset Text
486
487 \layout Standard
488
489 setxattr
490 \end_inset 
491 </cell>
492 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
493 \begin_inset Text
494
495 \layout Standard
496
497 yes
498 \end_inset 
499 </cell>
500 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
501 \begin_inset Text
502
503 \layout Standard
504
505 \end_inset 
506 </cell>
507 </row>
508 <row topline="true">
509 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
510 \begin_inset Text
511
512 \layout Standard
513
514 getxattr
515 \end_inset 
516 </cell>
517 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
518 \begin_inset Text
519
520 \layout Standard
521
522 no
523 \end_inset 
524 </cell>
525 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
526 \begin_inset Text
527
528 \layout Standard
529
530 \end_inset 
531 </cell>
532 </row>
533 <row topline="true">
534 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
535 \begin_inset Text
536
537 \layout Standard
538
539 listxattr
540 \end_inset 
541 </cell>
542 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
543 \begin_inset Text
544
545 \layout Standard
546
547 no
548 \end_inset 
549 </cell>
550 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
551 \begin_inset Text
552
553 \layout Standard
554
555 \end_inset 
556 </cell>
557 </row>
558 <row topline="true" bottomline="true">
559 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
560 \begin_inset Text
561
562 \layout Standard
563
564 removexattr
565 \end_inset 
566 </cell>
567 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
568 \begin_inset Text
569
570 \layout Standard
571
572 yes
573 \end_inset 
574 </cell>
575 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
576 \begin_inset Text
577
578 \layout Standard
579
580 \end_inset 
581 </cell>
582 </row>
583 </lyxtabular>
584
585 \end_inset 
586
587
588 \layout Itemize
589
590 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on victim.
591 \layout Itemize
592
593 cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
594 \layout Itemize
595
596 ->truncate() is never called directly - it's a callback, not a method.
597  It's called by vmtruncate() - library function normally used by ->setattr().
598  Locking information above applies to that call (i.e.
599  is inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had
600  been passed).
601  
602 \layout Standard
603
604 All inode operations may block so plugin can also block.
605  All critical inode operations is already protected by semaphore i_sem.
606 \layout Subsubsection*
607
608
609 \emph on 
610 File operations
611 \layout Standard
612
613 Locking rules: file operations may block and no BKL here.
614  
615 \layout Standard
616
617 Some hooks placed around file operations so protection needed to provide
618  sync execution of pre- and post-hooks with backfs operation.
619  
620 \layout Subsubsection*
621
622
623 \emph on 
624 Superblock operations
625 \layout Standard
626
627 Locking rules: All may block, only 
628 \emph on 
629 put_super 
630 \emph default 
631 is under BKL.
632  
633 \layout Standard
634
635 No hooks here, so no actions are needed.
636 \layout Subsubsection*
637
638 File operations
639 \layout Standard
640
641 locking rules: All may block.
642  
643 \layout Standard
644
645 None is under BKL except 
646 \emph on 
647 ioctl
648 \layout Comment
649
650 Taken from ..../linux/Documentation/filesystems/Locking
651 \layout Subsubsection
652
653 Upcall handling
654 \layout Standard
655
656 There is upcall API in SMFS.
657  Upcalls are organized in linked list and called one by one where needed.
658  
659 \layout Subsubsection
660
661 Fsfilt operations
662 \layout Standard
663
664 LVFS has fsfilt operations for SMFS.
665  SMFS store copy of fsfilt operations from backstore filesystem.
666  If it gets fsfilt operations then it is passed to backstore filesysem.
667  
668 \layout Subsubsection
669
670 Transactions handling
671 \layout Standard
672
673 All hooks should be in the same transaction with backstore fs operation.
674  To provide this SMFS starts transaction before first hook and commit after
675  last one.
676  SMFS care about transaction where it is needed, but plugins can add some
677  stuff to it.
678  To solve this SMFS pass transaction handler to plugin, so it can do transaction
679  in right way.
680  Also plugin should provide method to calculate extra size for transaction.
681 \layout Subsection
682
683 Backstore filesystem
684 \layout Subsubsection
685
686 Initialization
687 \layout Enumerate
688
689 Backstore FS is mounted by SMFS while initialization, if mount is failed
690  SMFS initialization is also failed.
691 \layout Enumerate
692
693 SMFS creates own superblock using backstore one and fsfilter operations
694 \layout Subsubsection
695
696 Superblock operations
697 \layout Standard
698
699 SMFS have to initialize own inode structure reading inode with same number
700  from backstore FS.
701  Operations with such inode will be redirected to backstore FS if they are
702  invoked.
703  SMFS will store backstore FS inode to avoid reading inode every time.
704  
705 \layout Subsubsection
706
707 Inode operations
708 \layout Standard
709
710 SMFS creates own inode operations for each inode.
711  When some operations in invoked SMFS calls real filesystem method to complete
712  it.
713  
714 \layout Standard
715
716 There are additional actions for making SMFS inode and real inode consistent.
717  These actions are needed before real operation to create artificial objects
718  and after - to copy changes from backfs inode.
719  
720 \layout Subsubsection
721
722 File operations
723 \layout Standard
724
725 SMFS creates own filp, duplicate backstore FS filp and dentry.
726  They are used in file operations following by backstore operation call.
727  To do file operations we create artificial file object before calling of
728  real operation.
729 \layout Section
730
731
732 \noun on 
733 Use cases
734 \layout Subsection
735
736 Backstore filesystem
737 \layout Standard
738
739 Next options is passed to smfs and descript backstore FS completely:
740 \layout Standard
741
742 smfs dev=/mnt type=ldiskfs
743 \layout Subsection
744
745 SMFS plugins/upcalls
746 \layout Subsubsection
747
748 SMFS plugin activation
749 \layout Standard
750
751 Now all plugins are compiled in SMFS module and plugins are setted up via
752  options when SMFS is mounting.
753  Options should be passed as mountfsoptions like this: 
754 \emph on 
755 ...
756  [kml|cache|snap...]
757 \layout Subsubsection
758
759 SMFS plugin registration
760 \layout Standard
761
762 Plugins should registers with SMFS:
763 \layout LyX-Code
764
765 smfs_register_plugin(parameters);
766 \layout Standard
767
768 Parameters are struct smfs_plugin filled with valid data:
769 \layout Itemize
770
771 type of plugin - to distinguish it from anothers,
772 \layout Itemize
773
774 pre_op function - function that will be called before fs operation,
775 \layout Itemize
776
777 post_op function - function that will be called after fs operation,
778 \layout Itemize
779
780 helper function - helper function.
781  See Plugin API,
782 \layout Itemize
783
784 any private data - data which will be return to plugin in each call.
785 \layout Subsubsection
786
787 SMFS hook invokation
788 \layout Standard
789
790 SMFS place special wrapper in own filesystem operations to call plugins
791  hook:
792 \layout LyX-Code
793
794 /* this is wrapper that calls all hooks walking through the list */
795 \layout LyX-Code
796
797 SMFS_HOOK(opcode, parameters);
798 \layout LyX-Code
799
800 \layout Standard
801
802 Hooks are placed in SMFS methods before and after calling backstore FS operation
803 s:
804 \layout LyX-Code
805
806 /* this is how to SMFS uses hooks */
807 \layout LyX-Code
808
809 smfs_some_op()
810 \layout LyX-Code
811
812
813 \layout LyX-Code
814
815         struct inode * backfs_inode = I2CI(inode);
816 \layout LyX-Code
817
818         struct smfs_file_info *sfi;
819 \layout LyX-Code
820
821        
822 \layout LyX-Code
823
824         SMFS_HOOK(hook_opcode, ...);
825 \layout LyX-Code
826
827         backfs_inode->i_fop->some_op(sfi->c_file, ...);
828 \layout LyX-Code
829
830         SMFS_HOOK(hook_opcode, ...);
831 \layout LyX-Code
832
833 }
834 \layout Subsubsection
835
836 SMFS upcall usage
837 \layout Standard
838
839 Upcalls can be placed in any place in SMFS, where side modules wants to
840  take control from SMFS.
841  Module should:
842 \layout Enumerate
843
844 prepares function to handle upcall events,
845 \layout Enumerate
846
847 registers upcall using upcall API,
848 \layout Enumerate
849
850 receives upcalls and handles they,
851 \layout Enumerate
852
853 deregisters upcall when smfs is unmounted.
854 \layout Section
855
856
857 \noun on 
858 Logic
859 \noun default 
860  
861 \noun on 
862 Specification
863 \layout Subsection
864
865 SMFS operations
866 \layout Subsubsection
867
868 Initialization and data structures
869 \layout Standard
870
871
872 \begin_inset ERT
873 status Open
874
875 \layout Standard
876
877 \backslash 
878 lst{../../include/linux/lustre_smfs.h}{Superblock info}{firstline=87,lastline=108}
879 \end_inset 
880
881
882 \layout LyX-Code
883
884 struct smfs_inode_info {
885 \layout LyX-Code
886
887         /* this first part of struct should be 
888 \layout LyX-Code
889
890            the same as in mds_info_info */
891 \layout LyX-Code
892
893         struct lustre_id smi_id;
894 \layout LyX-Code
895
896         
897 \layout LyX-Code
898
899         /* smfs part.
900  */
901 \layout LyX-Code
902
903         struct inode * backfs_inode;
904 \layout LyX-Code
905
906         __u32  smi_flags; //plugins pre_inode flags
907 \layout LyX-Code
908
909         struct list_head plist; /* list of plugins inode info */
910 \layout LyX-Code
911
912 }; 
913 \layout Standard
914
915
916 \begin_inset ERT
917 status Open
918
919 \layout Standard
920
921 \backslash 
922 lst{../../include/linux/lustre_smfs.h}{File info}{firstline=113,lastline=117}
923 \end_inset 
924
925
926 \layout Subsubsection
927
928 Fsfilt operations
929 \layout Standard
930
931 Fsfilt operations for SMFS just call the same operations in backstore FS.
932 \layout Standard
933
934
935 \begin_inset ERT
936 status Open
937
938 \layout Standard
939
940 \backslash 
941 lst{../../lvfs/fsfilt_smfs.c}{Fsfilt redirection example}{firstline=363,lastline=383}
942 \end_inset 
943
944
945 \layout Subsubsection
946
947 Transactions handling
948 \layout Standard
949
950 Each operations with hooks pass transaction handler to hook.
951  Hook can use it to decide does it need start new transaction or not.
952 \layout Standard
953
954 If there is no handler, hook can create own transaction:
955 \layout LyX-Code
956
957 hook_func_in_plugin()
958 \layout LyX-Code
959
960 {
961 \layout LyX-Code
962
963         ...
964 \layout LyX-Code
965
966         if (!handle) {
967 \layout LyX-Code
968
969                 handle = smfs_trans_start(inode, KML_CACHE_NOOP, NULL);
970 \layout LyX-Code
971
972         }
973 \layout LyX-Code
974
975         ...
976 \layout LyX-Code
977
978 }
979 \layout Standard
980
981 It is important that plugin should also commit transaction in the same call.
982  
983 \layout Standard
984
985 If transaction begun before hook call it should know size of transaction,
986  so we should provide a way to calculate this size through all plugins involved.
987  Each plugin can register upcall with related type that will return extra
988  size needed by that plugin.
989  SMFS will walk through upcalls and gets total extra size for transaction:
990  
991 \layout LyX-Code
992
993 fsfilt_smfs_start(struct inode * inode, int op, ...)
994 \layout LyX-Code
995
996 {
997 \layout LyX-Code
998
999         ...
1000 \layout LyX-Code
1001
1002         SMFS_TRANS_EXTRA_SIZE(inode, op); /* walking through list of plugins
1003  */
1004 \layout LyX-Code
1005
1006         handle = cache_fsfilt->fs_start(cache_inode, op, ...);
1007 \layout LyX-Code
1008
1009         ...
1010 \layout LyX-Code
1011
1012 }
1013 \layout Comment
1014
1015 still have no good idea how to pass calculated size instead op without changes
1016  in fsfilt_ext3/any_other_fs code.
1017  New parameter in fs_start?
1018 \layout Subsection
1019
1020 Backstore filesystem
1021 \layout Subsubsection
1022
1023 Initialization/deinitialization
1024 \layout Standard
1025
1026 Backstore FS is mounted by SMFS while SMFS initialization.
1027 \layout Standard
1028
1029
1030 \begin_inset ERT
1031 status Open
1032
1033 \layout Standard
1034
1035 \backslash 
1036 lst{../../smfs/smfs_lib.c}{Mount/Umount}{firstline=96,lastline=149}
1037 \end_inset 
1038
1039
1040 \layout Subsubsection
1041
1042 Inode\SpecialChar ~
1043 info init/clear
1044 \layout Standard
1045
1046 For each new inode SMFS creates private structures and getting real inode
1047  from backstore FS.
1048  SMFS is only user of backfs inode, so it is enough to get it here and put
1049  it down in clear_inode_info.
1050  Some plugins can have as SMFS-wide info as per-inode info.
1051  Therefore they can also participate in init_inode_info/clear_inode_info
1052  methods.
1053  Here are helpers for this.
1054 \layout LyX-Code
1055
1056 static void smfs_init_inode_info(struct inode *inode, void *opaque) {
1057 \layout LyX-Code
1058
1059         struct inode *cache_inode = NULL;
1060 \layout LyX-Code
1061
1062         struct smfs_iget_args *sargs;
1063 \layout LyX-Code
1064
1065         unsigned long ino;
1066 \layout LyX-Code
1067
1068 \layout LyX-Code
1069
1070         sargs = (struct smfs_iget_args *)opaque;
1071 \layout LyX-Code
1072
1073         /* getting backing fs inode.
1074  */
1075 \layout LyX-Code
1076
1077         ino = sargs ? sargs->s_ino : inode->i_ino;
1078 \layout LyX-Code
1079
1080         cache_inode = iget(S2CSB(inode->i_sb), ino); 
1081 \layout LyX-Code
1082
1083         OBD_ALLOC(inode->u.generic_ip, sizeof(struct smfs_inode_info));
1084 \layout LyX-Code
1085
1086         I2CI(inode) = cache_inode;
1087 \layout LyX-Code
1088
1089         post_smfs_inode(inode, cache_inode);
1090 \layout LyX-Code
1091
1092         sm_set_inode_ops(cache_inode, inode);
1093 \layout LyX-Code
1094
1095         if (sargs && sargs->s_inode)
1096 \layout LyX-Code
1097
1098                 I2SMI(inode)->smi_flags = I2SMI(sargs->s_inode)->smi_flags;
1099 \layout LyX-Code
1100
1101         SMFS_PLUGIN_HELPER(PL_INIT_INODE, inode);
1102 \layout LyX-Code
1103
1104 }
1105 \layout LyX-Code
1106
1107 \layout LyX-Code
1108
1109 static void smfs_clear_inode_info(struct inode *inode) {
1110 \layout LyX-Code
1111
1112         if (I2SMI(inode)) {
1113 \layout LyX-Code
1114
1115                 struct inode *cache_inode = I2CI(inode);
1116 \layout LyX-Code
1117
1118                 if (cache_inode != cache_inode->i_sb->s_root->d_inode)
1119 \layout LyX-Code
1120
1121                         iput(cache_inode);
1122 \layout LyX-Code
1123
1124                 SMFS_PLUGIN_HELPER(PL_CLEAR_INODE, inode);
1125 \layout LyX-Code
1126
1127                 OBD_FREE(inode->u.generic_ip, sizeof(struct smfs_inode_info));
1128 \layout LyX-Code
1129
1130                 inode->u.generic_ip = NULL;
1131 \layout LyX-Code
1132
1133         }
1134 \layout LyX-Code
1135
1136 }
1137 \layout LyX-Code
1138
1139 \layout Subsubsection
1140
1141 Getting inode
1142 \layout Comment
1143
1144 test_inode and set_inode are called under spinlock, so context-switching
1145  is not allowed here.
1146  Inode will be read after iget5_locked call 
1147 \layout LyX-Code
1148
1149 int smfs_test_inode(struct inode * inode, void * opaque)
1150 \layout LyX-Code
1151
1152 {
1153 \layout LyX-Code
1154
1155         struct smfs_iget_args * sargs = opaque;
1156 \layout LyX-Code
1157
1158         struct smfs_up_message message;
1159 \layout LyX-Code
1160
1161  
1162 \layout LyX-Code
1163
1164         message.inode = inode;
1165 \layout LyX-Code
1166
1167         message.param = opaque;
1168 \layout LyX-Code
1169
1170         
1171 \layout LyX-Code
1172
1173         if (sargs && (inode->i_ino == sargs->s_ino)) {
1174 \layout LyX-Code
1175
1176                 /* some module can add extra checks here */
1177 \layout LyX-Code
1178
1179                 if (SMFS_UPCALL(SMFS_UP_TEST_INODE, (void*)&message))
1180 \layout LyX-Code
1181
1182                         return 1;
1183 \layout LyX-Code
1184
1185         }
1186 \layout LyX-Code
1187
1188         return 0;
1189 \layout LyX-Code
1190
1191 }
1192 \layout LyX-Code
1193
1194 \layout LyX-Code
1195
1196 int smfs_set_inode(struct inode *inode, void *opaque)
1197 \layout LyX-Code
1198
1199 {
1200 \layout LyX-Code
1201
1202         struct smfs_up_message message;
1203 \layout LyX-Code
1204
1205  
1206 \layout LyX-Code
1207
1208         message.inode = inode;
1209 \layout LyX-Code
1210
1211         message.param = opaque;
1212 \layout LyX-Code
1213
1214 \layout LyX-Code
1215
1216         /* someone can wants to do action here */
1217 \layout LyX-Code
1218
1219         SMFS_UPCALL(SMFS_UP_SET_INODE, (void*)&message);
1220 \layout LyX-Code
1221
1222         return 0; 
1223 \layout LyX-Code
1224
1225 }
1226 \layout LyX-Code
1227
1228 \layout LyX-Code
1229
1230 struct inode * smfs_iget(struct super_block * sb, ino_t hash,
1231 \layout LyX-Code
1232
1233                          struct smfs_iget_args * sargs)
1234 \layout LyX-Code
1235
1236 {
1237 \layout LyX-Code
1238
1239         struct inode *inode;
1240 \layout LyX-Code
1241
1242         inode = iget5_locked(sb, hash, smfs_test_inode,
1243 \layout LyX-Code
1244
1245                              smfs_set_inode, sargs);
1246 \layout LyX-Code
1247
1248         if (inode) {
1249 \layout LyX-Code
1250
1251                 if (inode->i_state & I_NEW) {
1252 \layout LyX-Code
1253
1254                         smfs_init_inode_info(inode, sargs);
1255 \layout LyX-Code
1256
1257                         unlock_new_inode(inode);
1258 \layout LyX-Code
1259
1260                 }
1261 \layout LyX-Code
1262
1263                 inode->i_ino = hash;
1264 \layout LyX-Code
1265
1266         }
1267 \layout LyX-Code
1268
1269         return inode;
1270 \layout LyX-Code
1271
1272 }
1273 \layout Subsubsection
1274
1275 Superblock operations
1276 \layout Paragraph
1277
1278 read\SpecialChar ~
1279 inode2()
1280 \layout LyX-Code
1281
1282 smfs_read_inode2 (struct inode * inode, void * opaque) 
1283 \layout LyX-Code
1284
1285 {
1286 \layout LyX-Code
1287
1288         smfs_init_inode_info(inode, opaque);
1289 \layout LyX-Code
1290
1291 }
1292 \layout Paragraph
1293
1294 dirty\SpecialChar ~
1295 inode()/write\SpecialChar ~
1296 inode()
1297 \layout LyX-Code
1298
1299 smfs_dirty/write_inode(struct inode * inode)
1300 \layout LyX-Code
1301
1302 {
1303 \layout LyX-Code
1304
1305         backfs_inode = I2CI(inode);
1306 \layout LyX-Code
1307
1308         backfs_sb->s_op->dirty/write_inode(backfs_inode);
1309 \layout LyX-Code
1310
1311         duplicate_inode(inode, backfs_inode);
1312 \layout LyX-Code
1313
1314 }
1315 \layout Paragraph
1316
1317 put\SpecialChar ~
1318 inode(inode)
1319 \layout LyX-Code
1320
1321 smfs_put_inode(struct inode * inode)
1322 \layout LyX-Code
1323
1324 {
1325 \layout LyX-Code
1326
1327         return;
1328 \layout LyX-Code
1329
1330 }
1331 \layout Paragraph
1332
1333 delete\SpecialChar ~
1334 inode()
1335 \layout LyX-Code
1336
1337 smfs_delete_inode(struct inode * inode) {
1338 \layout LyX-Code
1339
1340         clear_inode(inode);
1341 \layout LyX-Code
1342
1343 }
1344 \layout Paragraph
1345
1346 clear\SpecialChar ~
1347 inode()
1348 \layout LyX-Code
1349
1350 smfs_clear_inode(struct inode * inode) {
1351 \layout LyX-Code
1352
1353         smfs_clear_inode_info(inode);
1354 \layout LyX-Code
1355
1356 }
1357 \layout Paragraph
1358
1359 put\SpecialChar ~
1360 super(super)
1361 \layout LyX-Code
1362
1363 smfs_cleanup_hooks();
1364 \layout LyX-Code
1365
1366 smfs_umount_cache(smfs_super_info);
1367 \layout LyX-Code
1368
1369 smfs_cleanup_smb(sb);    
1370 \layout Paragraph
1371
1372 write\SpecialChar ~
1373 super()/write\SpecialChar ~
1374 super\SpecialChar ~
1375 lockfs()/unlockfs()/statfs()/remountfs()
1376 \layout LyX-Code
1377
1378 backfs_sb = S2CSB(sb);
1379 \layout LyX-Code
1380
1381 backfs_sb->s_op->...;
1382 \layout LyX-Code
1383
1384 duplicate-sb(sb, backfs_sb);
1385 \layout Subsubsection
1386
1387 Inode operations
1388 \layout Standard
1389
1390 Each inode operaion uses backfs inode structure, this structure is created
1391  while several fs operations are invoked.
1392  Logic of all operations is next:
1393 \layout Itemize
1394
1395 There is smfs dentry for each operation passed as parameter
1396 \layout Itemize
1397
1398 SMFS creates artificial dentries for using they in backstore fs operation
1399 \layout Itemize
1400
1401 after operation there is backstore fs inode in backfs_dentry->d_inode
1402 \layout Itemize
1403
1404 if SMFS inode not exits it is created here and connected to backfs inode
1405 \layout Itemize
1406
1407 several fields are copied from backstore fs inode to smfs one
1408 \layout Itemize
1409
1410 all artificial dentries are cleared.
1411 \layout Standard
1412
1413
1414 \emph on 
1415 Artificial dentry handling
1416 \layout LyX-Code
1417
1418 struct dentry *pre_smfs_dentry(struct dentry *parent_dentry, struct inode
1419  *cache_inode,
1420 \layout LyX-Code
1421
1422                                struct dentry *dentry) {
1423 \layout LyX-Code
1424
1425         struct dentry *cache_dentry = NULL;
1426 \layout LyX-Code
1427
1428         cache_dentry = d_alloc(parent_dentry, &dentry->d_name);
1429 \layout LyX-Code
1430
1431         if (!cache_dentry)
1432 \layout LyX-Code
1433
1434                 RETURN(NULL);
1435 \layout LyX-Code
1436
1437         if (!parent_dentry)
1438 \layout LyX-Code
1439
1440                 cache_dentry->d_parent = cache_dentry;
1441 \layout LyX-Code
1442
1443         if (cache_inode)
1444 \layout LyX-Code
1445
1446                 d_add(cache_dentry, cache_inode);
1447 \layout LyX-Code
1448
1449         RETURN(cache_dentry);
1450 \layout LyX-Code
1451
1452 }
1453 \layout LyX-Code
1454
1455 \layout LyX-Code
1456
1457 void post_smfs_dentry(struct dentry *cache_dentry) {
1458 \layout LyX-Code
1459
1460         if (!cache_dentry)
1461 \layout LyX-Code
1462
1463                 return;
1464 \layout LyX-Code
1465
1466         d_unalloc(cache_dentry);
1467 \layout LyX-Code
1468
1469
1470 \layout Standard
1471
1472 For inode operation we have parent inode and dentry for operation.
1473  So SMFS has to create artificial parent dentry with backfs_inode connected
1474  to it and artificial dentry for ext3 operation.
1475  This is done with pre_smfs_dentry() method.
1476 \layout Standard
1477
1478 After successfull creation SMFS will do backfs operation and gets filled
1479  artificial dentry.
1480  Next step is getting SMFS inode from cache using ext3 inode number.
1481  If inode is found it is connected to smfs dentry and operation can be counted
1482  as completed.
1483  SMFS clean all artificial dentries and exits.
1484 \layout Standard
1485
1486
1487 \emph on 
1488 duplicate_inode details
1489 \layout Standard
1490
1491
1492 \begin_inset ERT
1493 status Open
1494
1495 \layout Standard
1496
1497 \backslash 
1498 lst{../../include/linux/lustre_smfs.h}{Duplicate
1499 \backslash 
1500 _inode()}{firstline=298,lastline=317}
1501 \end_inset 
1502
1503
1504 \layout Standard
1505
1506
1507 \emph on 
1508 Inode operations
1509 \layout Standard
1510
1511
1512 \begin_inset ERT
1513 status Open
1514
1515 \layout Standard
1516
1517 \backslash 
1518 lst{../../smfs/dir.c}{Create()}{firstline=44,lastline=577}
1519 \end_inset 
1520
1521
1522 \layout Standard
1523
1524
1525 \begin_inset ERT
1526 status Open
1527
1528 \layout Standard
1529
1530 \backslash 
1531 lst{../../smfs/file.c}{Truncate()}{firstline=378,lastline=533}
1532 \end_inset 
1533
1534
1535 \layout Subsubsection
1536
1537 File operations
1538 \layout Standard
1539
1540 SMFS creates artificial struct file object for each SMFS file struct and
1541  use it for backstore fs operations.
1542  Backstore struct file is created in open() method and connected to private
1543  field in smfs struct file.
1544  This struct will be released in smfs_release().
1545 \layout Standard
1546
1547 When created and modified this struct file is duplicated to smfs one:
1548 \layout Standard
1549
1550
1551 \emph on 
1552 duplicate_file
1553 \layout Standard
1554
1555
1556 \begin_inset ERT
1557 status Open
1558
1559 \layout Standard
1560
1561 \backslash 
1562 lst{../../include/linux/lustre_smfs.h}{duplicate
1563 \backslash 
1564 _file()}{firstline=343,lastline=361}
1565 \end_inset 
1566
1567
1568 \layout Paragraph
1569
1570 Common case (write/read/llseek/mmap/ioctl/readdir)
1571 \layout LyX-Code
1572
1573
1574 \layout LyX-Code
1575
1576         struct inode * backfs_inode;
1577 \layout LyX-Code
1578
1579         struct smfs_file_info *sfi;
1580 \layout LyX-Code
1581
1582        
1583 \layout LyX-Code
1584
1585         backfs_inode = I2CI(file->f_dentry->d_inode);
1586 \layout LyX-Code
1587
1588         sfi = F2SMFI(file);
1589 \layout LyX-Code
1590
1591         pre_smfs_inode(file->f_dentry->d_inode, backfs_inode);
1592 \layout LyX-Code
1593
1594         SMFS_HOOK(..., hook_opcode , ..., PRE_HOOK, ...);
1595 \layout LyX-Code
1596
1597         if (backfs_inode->i_fop->...)
1598 \layout LyX-Code
1599
1600                 backfs_inode->i_fop->...(sfi->c_file, ...);
1601 \layout LyX-Code
1602
1603         SMFS_HOOK(..., hook_opcode, ..., POST_HOOK, ...);
1604 \layout LyX-Code
1605
1606         post_smfs_inode(file->f_dentry->d_inode, backfs_inode); /* duplicate_ino
1607 de */
1608 \layout LyX-Code
1609
1610         duplicate_file(file, sfi->c_file);
1611 \layout LyX-Code
1612
1613
1614 \layout Paragraph
1615
1616 fsync()
1617 \layout LyX-Code
1618
1619 int smfs_fsync(struct file *file, struct dentry *dentry, int datasync)
1620 \layout LyX-Code
1621
1622 {
1623 \layout LyX-Code
1624
1625         struct smfs_file_info *sfi = NULL;
1626 \layout LyX-Code
1627
1628         struct dentry *backfs_dentry = NULL;
1629 \layout LyX-Code
1630
1631         struct file *backfs_file = NULL;
1632 \layout LyX-Code
1633
1634         struct inode *backfs_inode = NULL;
1635 \layout LyX-Code
1636
1637 \layout LyX-Code
1638
1639         backfs_inode = I2CI(dentry->d_inode);
1640 \layout LyX-Code
1641
1642         backfs_dentry = pre_smfs_dentry(NULL, backfs_inode, dentry);
1643 \layout LyX-Code
1644
1645         if (file) {
1646 \layout LyX-Code
1647
1648                 sfi = F2SMFI(file);
1649 \layout LyX-Code
1650
1651                 backfs_file = sfi->c_file;
1652 \layout LyX-Code
1653
1654         } 
1655 \layout LyX-Code
1656
1657         pre_smfs_inode(dentry->d_inode, backfs_inode);
1658 \layout LyX-Code
1659
1660         if (backfs_inode->i_fop->fsync) {
1661 \layout LyX-Code
1662
1663                 rc = backfs_inode->i_fop->fsync(backfs_file, backfs_dentry,
1664  datasync);
1665 \layout LyX-Code
1666
1667         }
1668 \layout LyX-Code
1669
1670         post_smfs_inode(dentry->d_inode, backfs_inode);
1671 \layout LyX-Code
1672
1673         duplicate_file(file, backfs_file);
1674 \layout LyX-Code
1675
1676         post_smfs_dentry(backfs_dentry);
1677 \layout LyX-Code
1678
1679
1680 \layout Paragraph
1681
1682 open()
1683 \layout LyX-Code
1684
1685 int smfs_open(struct inode *inode, struct file *filp) 
1686 \layout LyX-Code
1687
1688 {
1689 \layout LyX-Code
1690
1691         struct inode *backfs_inode = NULL;
1692 \layout LyX-Code
1693
1694         
1695 \layout LyX-Code
1696
1697         backfs_inode = I2CI(inode);
1698 \layout LyX-Code
1699
1700         smfs_init_cache_file(inode, filp);
1701 \layout LyX-Code
1702
1703         if (backfs_inode->i_fop->open)
1704 \layout LyX-Code
1705
1706                 rc = cache_inode->i_fop->open(backfs_inode, F2CF(filp));
1707 \layout LyX-Code
1708
1709         duplicate_file(filp, F2CF(filp));
1710 \layout LyX-Code
1711
1712
1713 \layout Paragraph
1714
1715 release()
1716 \layout LyX-Code
1717
1718 int smfs_release(struct inode *inode, struct file *filp) 
1719 \layout LyX-Code
1720
1721 {
1722 \layout LyX-Code
1723
1724         struct inode *backfs_inode = NULL;
1725 \layout LyX-Code
1726
1727         struct file *backfs_file = NULL;
1728 \layout LyX-Code
1729
1730         struct smfs_file_info *sfi = NULL;
1731 \layout LyX-Code
1732
1733 \layout LyX-Code
1734
1735         backfs_inode = I2CI(inode);
1736 \layout LyX-Code
1737
1738         if (filp) {
1739 \layout LyX-Code
1740
1741                 sfi = F2SMFI(filp);
1742 \layout LyX-Code
1743
1744                 backfs_file = sfi->c_file;
1745 \layout LyX-Code
1746
1747         }
1748 \layout LyX-Code
1749
1750         if (backfs_inode->i_fop->release)
1751 \layout LyX-Code
1752
1753                 backfs_inode->i_fop->release(backfs_inode, backfs_file);
1754 \layout LyX-Code
1755
1756         post_smfs_inode(inode, backfs_inode);
1757 \layout LyX-Code
1758
1759         smfs_cleanup_cache_file(filp);
1760 \layout LyX-Code
1761
1762
1763 \layout Section
1764
1765 State Specification
1766 \layout Subsection
1767
1768 Transactions
1769 \layout Standard
1770
1771 There are several situations are possible with transactions.
1772  SMFS doesn't know will plugin do transaction or not.
1773  
1774 \layout Subsubsection
1775
1776 Backstore FS will do transaction
1777 \layout Standard
1778
1779 In that case plugins actions should be in same transaction with backstore
1780  FS.
1781  Next actions will be done:
1782 \layout Enumerate
1783
1784 SMFS gets extra size for current operation from all plugins.
1785 \layout Enumerate
1786
1787 If extra size is not null then some plugins will participate in transaction.
1788  SMFS starts transaction with calculated size.
1789 \layout Enumerate
1790
1791 SMFS call pre_hook.
1792 \layout Enumerate
1793
1794 SMFS call backstore FS operation.
1795 \layout Enumerate
1796
1797 SMFS call post_hook.
1798 \layout Enumerate
1799
1800 SMFS commit transaction.
1801 \layout Subsubsection
1802
1803 Backstore FS operation is not journaled
1804 \layout Standard
1805
1806 In that case plugins may don't care about external conditions and do transaction
1807  by own:
1808 \layout Enumerate
1809
1810 SMFS call pre_hook or post_hook
1811 \layout Enumerate
1812
1813 Plugin starts transaction.
1814  
1815 \layout Enumerate
1816
1817 Plugin do what it should.
1818 \layout Enumerate
1819
1820 Plugin commit transaction.
1821 \layout Standard
1822
1823 Transaction MUST be commited where it was started.
1824  It is not allowed to start it in pre_hook and commit in post_hook.
1825 \layout Subsection
1826
1827 Locking
1828 \layout Subsubsection
1829
1830 Inode operations
1831 \layout Enumerate
1832
1833 VFS calls SMFS operation and takes i_sem.
1834 \layout Enumerate
1835
1836 SMFS does pre_hook operation, calls backstore FS operation and then - post_hook.
1837 \layout Standard
1838
1839 All operations are protected by i_sem in SMFS inode.
1840  But there are possible situations when plugin hook sequence will be like
1841  this:
1842 \layout Itemize
1843
1844 pre_hook(inode1)
1845 \layout Itemize
1846
1847 pre_hook(inode2)
1848 \layout Itemize
1849
1850 post_hooks(...)
1851 \layout Standard
1852
1853 This is possible because inode1 may block and operation for inode2 will
1854  starts.
1855  Plugin should be aware about that and use additional protection if it is
1856  needed.
1857  
1858 \layout Subsubsection
1859
1860 File operations
1861 \layout Standard
1862
1863 File operations are not protected right now.
1864  SMFS can also use i_sem to protect these operations, but previous words
1865  about operations order are make sense here also.
1866 \the_end