ダウンロード: vfs.txt
現在作業中の文書です。お気づきの点がありましたら、jf@listserv.linux.or.jp、チケット、フォーラムのいずれかにお寄せください。
========================================================= これは、 Linux-2.6.34/Documentation/filesystems/vfs.txt の和訳です。 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > 更新日 : 2010/06/13 翻訳者 : Seiji Kaneko < skaneko at mbn dot or dot jp > チェック者: Bun Mizuhara < mizuhara at acm org > ========================================================= # Overview of the Linux Virtual File System Linux 仮想ファイルシステム (Virtual File System) 概説 # Original author: Richard Gooch <rgooch@atnf.csiro.au> 原著者 Richard Gooch <rgooch@atnf.csiro.au> # Last updated on June 24, 2007. 最終更新 2007.6.24 Copyright (C) 1999 Richard Gooch Copyright (C) 2005 Pekka Enberg # This file is released under the GPLv2. このファイルは GPLv2.の元にリリースされています。 #Introduction #============ はじめに ======== #The Virtual File System (also known as the Virtual Filesystem Switch) #is the software layer in the kernel that provides the filesystem #interface to userspace programs. It also provides an abstraction #within the kernel which allows different filesystem implementations to #coexist. 仮想ファイルシステム (別名仮想ファイルシステムスイッチ) は、ファイルシス テムインターフェースをユーザプログラムに提供する、カーネル内のソフトウェ アレイヤです。これは同時にカーネル内での仮想化レイヤを提供し、異なったフ ァイルシステム実装を共存可能にします。 #VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so #on are called from a process context. Filesystem locking is described #in the document Documentation/filesystems/Locking. VFSシステムコール群 open(2), stat(2), read(2), write(2), chmod(2) など、 がプロセスコンテキストから呼ばれます。 ファイルシステムロックについては、 文書 Documentation/filesystems/Locking に記載されています。 #Directory Entry Cache (dcache) #------------------------------ ディレクトリエントリキャッシュ (dcache) --------------------------------------- #The VFS implements the open(2), stat(2), chmod(2), and similar system #calls. The pathname argument that is passed to them is used by the VFS #to search through the directory entry cache (also known as the dentry #cache or dcache). This provides a very fast look-up mechanism to #translate a pathname (filename) into a specific dentry. Dentries live #in RAM and are never saved to disc: they exist only for performance. VFS は open(2), stat(2), chmod(2) などのシステムコールを実装しています。 これらの関数に渡された pathname 引数は、VFS でディレクトリエントリキャッ シュ (別名 dentry キャッシュ、または dcache) を探索するために用いられます。 このキャッシュは、特定のパス名 (ファイル名) を特定の dentry に変換する、 極めて高速な検索メカニズムを提供します。Dentry は RAM 上に存在し、ディス クにセーブされることはありません。これらは性能向上のためだけに存在します。 #The dentry cache is meant to be a view into your entire filespace. As #most computers cannot fit all dentries in the RAM at the same time, #some bits of the cache are missing. In order to resolve your pathname #into a dentry, the VFS may have to resort to creating dentries along #the way, and then loading the inode. This is done by looking up the #inode. dentry キャッシュは、対象とするファイルシステム全体の覗き窓に当たります。 殆どのコンピュータではすべての dentry を RAM 上に同時に置くことはできな いため、キャッシュの一部の範囲は欠けています。指定したパス名を dentry に 変換するため、VFS はその過程となる dentry の作成を行いつつ inode のロード を行なう場合もあります。これは inode を検索することにより行なわれます。 #The Inode Object #---------------- Inode オブジェクト ------------------ #An individual dentry usually has a pointer to an inode. Inodes are #filesystem objects such as regular files, directories, FIFOs and other #beasts. They live either on the disc (for block device filesystems) #or in the memory (for pseudo filesystems). Inodes that live on the #disc are copied into the memory when required and changes to the inode #are written back to disc. A single inode can be pointed to by multiple #dentries (hard links, for example, do this). 個々の dentry は通常 inode へのポインタを持ちます。inode は通常のファイル、 ディレクトリ、FIFO などのファイルシステムオブジェクトです。これらはディス ク上 (ブロックデバイスファイルシステム) に存在するか、メモリ上 (疑似ファ イルシステム) に存在するかのいずれかです。ディスク上にある inode は必要に 応じてメモリにコピーされ、inode への変更はディスクに書き戻されます。単一 の inode を複数の dentry から指すことも可能です。例えばハードリンクにより この状態が起きます。 #To look up an inode requires that the VFS calls the lookup() method of #the parent directory inode. This method is installed by the specific #filesystem implementation that the inode lives in. Once the VFS has #the required dentry (and hence the inode), we can do all those boring #things like open(2) the file, or stat(2) it to peek at the inode #data. The stat(2) operation is fairly simple: once the VFS has the #dentry, it peeks at the inode data and passes some of it back to #userspace. inode を検索するには、VFS が親ディレクトリ inode の lookup() メソッドを 呼び出す必要があります。このメソッドは、inode が存在するファイルシステム 固有の実装として提供されています。VFS で必要な dentry (そして inode) が 得られれば、これらに対して、例えばファイルの open(2) や、inode データを stat(2) で覗くなどの、どんな退屈な処理でも可能です。stat(2) の動作は比較 的簡単です。VFS で必要な dentry (つまり inode) が得られれば、VFS は inode データを覗き、その一部をユーザ空間に返します。 #The File Object #--------------- ファイルオブジェクト -------------------- #Opening a file requires another operation: allocation of a file #structure (this is the kernel-side implementation of file #descriptors). The freshly allocated file structure is initialized with #a pointer to the dentry and a set of file operation member functions. #These are taken from the inode data. The open() file method is then #called so the specific filesystem implementation can do it's work. You #can see that this is another switch performed by the VFS. The file #structure is placed into the file descriptor table for the process. ファイルを開くにはまた別の処理、すなわちファイル構造体の割り付け (これは ファイルディスクリプタのカーネル側の実装です) が必要です。新規に割り当て られたデータ構造体は、dentry を指すポインタと一連の操作メンバ関数により初 期化されます。これらは inode データから取られます。次に open() ファイルメ ソッドが呼ばれ、ファイルシステム固有の実装が作業を行います。これは VFS が 行なうもう一つのスイッチ動作と見なせます。このファイル構造体がプロセスの ファイルディスクリプタテーブルに格納されます。 #Reading, writing and closing files (and other assorted VFS operations) #is done by using the userspace file descriptor to grab the appropriate #file structure, and then calling the required file structure method to #do whatever is required. For as long as the file is open, it keeps the #dentry in use, which in turn means that the VFS inode is still in use. ファイルの読み・書き・クローズ (及び関連するその他の VFS 操作) はユーザ 空間のファイルディスクリプタを使って適切なファイル構造をつかんでから、そ の要求された操作に対応するファイル構造体メソッドを呼び出すことで実行され ます。ファイルが open されているあいだは dentry は使用中に保たれ、dentry が使用中であるなら VFS inode もまだ使用中であることを意味します。 #Registering and Mounting a Filesystem #===================================== ファイルシステムを登録・マウントする ==================================== #To register and unregister a filesystem, use the following API #functions: ファイルシステムを登録または登録解除するには、以下の API 関数を用いてくだ さい。 #include <linux/fs.h> extern int register_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *); #The passed struct file_system_type describes your filesystem. When a #request is made to mount a device onto a directory in your filespace, #the VFS will call the appropriate get_sb() method for the specific #filesystem. The dentry for the mount point will then be updated to #point to the root inode for the new filesystem. 渡された構造体 file_system_type が、ファイルシステムの性質を記述しています。 ディレクトリにデバイスをマウントするリクエストが発行された場合、VFS はそのファイルシ ステムに対応した適切な get_sb() メソッドを呼び出し、次にマウントポイントの dentry が 新しいファイルシステムの root inode を指すよう更新されます。 #You can see all filesystems that are registered to the kernel in the #file /proc/filesystems. カーネルに登録されたファイルシステムの一覧を /proc/filesystems ファイルで見 ることができます。 #struct file_system_type #----------------------- struct file_system_type ----------------------- #This describes the filesystem. As of kernel 2.6.22, the following #members are defined: これはファイルシステムの種類を記述します。カーネル 2.6.22 では以下のメンバ が定義されています。 struct file_system_type { const char *name; int fs_flags; int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers; struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; }; # name: the name of the filesystem type, such as "ext2", "iso9660", # "msdos" and so on 名前: ファイルシステムタイプ名。例えば "ext2", "iso9660", "msdos" など # fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) fs_flags: 様々なフラグ (例: FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) # get_sb: the method to call when a new instance of this # filesystem should be mounted get_sb: このファイルシステムの新しいインスタンスをマウントする際に、この メソッドを呼びます。 # kill_sb: the method to call when an instance of this filesystem # should be unmounted kill_sb: このファイルシステムのインスタンスをアンマウントする際に、このメ ソッドを呼びます。 # owner: for internal VFS use: you should initialize this to THIS_MODULE in # most cases. owner: VFS の内部で使用します。この値はたいていの場合 THIS_MODULE に初期 化すべきです。 # next: for internal VFS use: you should initialize this to NULL next: VFS の内部で使用します。この値は NULL で初期化すべきです。 # s_lock_key, s_umount_key: lockdep-specific s_lock_key, s_umount_key: lockdep 固有です。 #The get_sb() method has the following arguments: get_sb() メソッドは以下の引数を取ります。 # struct file_system_type *fs_type: describes the filesystem, partly initialized # by the specific filesystem code struct file_system_type *fs_type: 対象ファイルシステム種別を記述します。構造体の一 部は対象ファイルシステム側のコードで初期化されます。 # int flags: mount flags int flags: マウントフラグ # const char *dev_name: the device name we are mounting. const char *dev_name: マウントしようとしているデバイス名 # void *data: arbitrary mount options, usually comes as an ASCII # string (see "Mount Options" section) void *data: 任意のマウントオプション。通常 ASCII 文字列として与えられます (Mount Options の節参照)。 # struct vfsmount *mnt: a vfs-internal representation of a mount point struct vfsmount *mnt: マウントポイントの VFS の内部表現 #The get_sb() method must determine if the block device specified #in the dev_name and fs_type contains a filesystem of the type the method #supports. If it succeeds in opening the named block device, it initializes a #struct super_block descriptor for the filesystem contained by the block device. #On failure it returns an error. get_sb() メソッドは、dev_name と fs_type で指定されたブロックデバイスが、このメソッド のサポートするタイプのファイルシステムであるかどうかを判定しなければいけません。名前 の示すブロックデバイスのオープンに成功したなら、ブロックデバイスが含むファイルシステ ムに対応して struct super_block ディスクリプタを初期化します。失敗時にはエラーを戻し ます。 #The most interesting member of the superblock structure that the #get_sb() method fills in is the "s_op" field. This is a pointer to #a "struct super_operations" which describes the next level of the #filesystem implementation. get_sb() メソッドが代入する最も重要なスーパーブロック構造体のメンバは s_op フィールド です。これは "struct super_operations" (struct super 向け操作) へのポインタで、この ような「操作」はファイルシステム実装の次のレベルを示すものです。 #Usually, a filesystem uses one of the generic get_sb() implementations #and provides a fill_super() method instead. The generic methods are: 通常、ファイルシステムは汎用の get_sb() 実装のうちの一つを使い、それを補うために fill_super() メソッドを提供するのです。汎用のメソッドは以下の通りです。 # get_sb_bdev: mount a filesystem residing on a block device get_sb_bdev: ブロックデバイス上のファイルシステムをマウントします。 # get_sb_nodev: mount a filesystem that is not backed by a device get_sb_nodev: デバイスの裏付けのないファイルシステムをマウントします。 # get_sb_single: mount a filesystem which shares the instance between # all mounts get_sb_single: インスタンスをすべてのマウントの間で共有するファイルシステムをマウン トします。 #A fill_super() method implementation has the following arguments: fill_super() メソッドの実装は以下の引数を取ります。 # struct super_block *sb: the superblock structure. The method fill_super() # must initialize this properly. struct super_block *sb: スーパーブロック構造体。fill_super() メソッドはこ のプロパティを初期化しなければなりません。 # void *data: arbitrary mount options, usually comes as an ASCII # string (see "Mount Options" section) void *data: 任意のマウントオプション。通常 ASCII 文字列として与えられます (Mount Options の節参照)。 # int silent: whether or not to be silent on error int silent: エラー時に報告するか否かを指定します。 #The Superblock Object #===================== スーパーブロックオブジェクト ============================ #A superblock object represents a mounted filesystem. スーパーブロックオブジェクトはマウントされたファイルシステムを表現するものです。 #struct super_operations #----------------------- super_operations 構造体 ----------------------- #This describes how the VFS can manipulate the superblock of your #filesystem. As of kernel 2.6.22, the following members are defined: ここでは、VFS があなたのファイルシステムのスーパーブロックをどのように操作 するかが記載されています。カーネル 2.6.22 では以下のメンバが定義されていま す。 struct super_operations { struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); void (*dirty_inode) (struct inode *); int (*write_inode) (struct inode *, int); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); int (*show_options)(struct seq_file *, struct vfsmount *); ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); }; #All methods are called without any locks being held, unless otherwise #noted. This means that most methods can block safely. All methods are #only called from a process context (i.e. not from an interrupt handler #or bottom half). すべてのメソッドは、特に注記なき限りロックを持たずに呼び出し可能です。従って、殆どの メソッドは安全にブロック可能です。すべてのメソッドはプロセスコンテキストからのみ呼び 出し可能です (即ち、割り込みハンドラやカーネルの下半分からの呼び出しはできません)。 # alloc_inode: this method is called by inode_alloc() to allocate memory # for struct inode and initialize it. If this function is not # defined, a simple 'struct inode' is allocated. Normally # alloc_inode will be used to allocate a larger structure which # contains a 'struct inode' embedded within it. alloc_inode: このメソッドは inode_alloc() から呼ばれ、inode 構造体のメモ リを割り当て、構造体を初期化します。この関数が定義されていない場合 は、単純な struct inode が割り当てられます。通常 alloc_inode は、 struct inode を内部に含む大きな構造体を割り当てる際に使用します。 # destroy_inode: this method is called by destroy_inode() to release # resources allocated for struct inode. It is only required if # ->alloc_inode was defined and simply undoes anything done by # ->alloc_inode. destroy_inode: このメソッドは destroy_inode() から、inode 構造体に割り当 てられたリソースを解放するために呼ばれます。このメソッドは ->alloc_inode が定義されている場合にのみ必要で、単に ->alloc_inode の行なったことすべてを取り消します。 # dirty_inode: this method is called by the VFS to mark an inode dirty. dirty_inode: このメソッドは、inode を Dirty にマークするため VFS から呼ばれます。 # write_inode: this method is called when the VFS needs to write an # inode to disc. The second parameter indicates whether the write # should be synchronous or not, not all filesystems check this flag. write_inode: このメソッドは、VFS が inode をディスクに書き込む必要がある とき呼ばれます。第二のパラメータは、書き込みを同期書き込みとすべき かそうでないかを示すものです。すべてのファイルシステムでこのフラグ がチェックされるわけではありません。 # drop_inode: called when the last access to the inode is dropped, # with the inode_lock spinlock held. drop_inode: inode の最後の参照が落とされた場合に呼ばれます。inode_lock スピンロック を保持している必要があります。 # This method should be either NULL (normal UNIX filesystem # semantics) or "generic_delete_inode" (for filesystems that do not # want to cache inodes - causing "delete_inode" to always be # called regardless of the value of i_nlink) このメソッドは NULL (通常の Unix ファイルシステムの挙動) か、 generic_delete_inode (inode のキャッシングを望まないファイルシステムでは。- この 場合 i_nlink の値によらず常に delete_inode が呼ばれます) のいずれか とすべきです。 # The "generic_delete_inode()" behavior is equivalent to the # old practice of using "force_delete" in the put_inode() case, # but does not have the races that the "force_delete()" approach # had. generic_delete_inode() での挙動は、以前の慣行で使用されていた put_inode() での force_delete を使用した場合と同じですが、force_delete() で発生する競合はこちらで は発生しません。 # delete_inode: called when the VFS wants to delete an inode delete_inode: このメソッドは、VFS が inode を削除しようとするとき呼ばれます。 # put_super: called when the VFS wishes to free the superblock # (i.e. unmount). This is called with the superblock lock held put_super: VFS がスーパーブロックを解放 (つまり、アンマウント) する際に呼 ばれます。このメソッドは superblock ロックを持った状態で呼び 出します。 # write_super: called when the VFS superblock needs to be written to # disc. This method is optional write_super: このメソッドは、VFS スーパーブロックをディスクに書き込む必要 がある場合に呼ばれます。このメソッドはオプションです。 # sync_fs: called when VFS is writing out all dirty data associated with # a superblock. The second parameter indicates whether the method # should wait until the write out has been completed. Optional. sync_fs: VFS がスーパーブロックに関連したすべての Dirty データを書き出すた めに呼ばれます。二番目のパラメータは、このメソッドが書き込みの終了を 待つかどうかを示します。このメソッドはオプションです。 # freeze_fs: called when VFS is locking a filesystem and # forcing it into a consistent state. This method is currently # used by the Logical Volume Manager (LVM). freeze_fs: VFS がファイルシステムをロックし、整合性の取れた状態に 強制的にする際に呼ばれます。このメソッドは現在 Logical Volume Manager (LVM) で使われています。 # unfreeze_fs: called when VFS is unlocking a filesystem and making it writable # again. unfreeze_fs: VFS がファイルシステムをアンロックし、再度書き込み可能にする際に 呼ばれます。 # statfs: called when the VFS needs to get filesystem statistics. statfs: VFS がファイルシステムの統計情報を得るために呼ばれます。 # remount_fs: called when the filesystem is remounted. This is called # with the kernel lock held remount_fs: ファイルシステムを再マウントする際に呼ばれます。これは kernel ロックを 持った状態で呼びます。 # clear_inode: called then the VFS clears the inode. Optional clear_inode: VFS が inode をクリアする場合呼ばれます。このメソッドはオプションです。 # # umount_begin: called when the VFS is unmounting a filesystem. umount_begin: VFS がファイルシステムをアンマウントする際に呼ばれます。 # show_options: called by the VFS to show mount options for # /proc/<pid>/mounts. (see "Mount Options" section) show_options: VFS により、 /proc/<pid>/mounts のマウントオプション を表示するために呼ばれます。( "Mount オプション" の節を参照) # quota_read: called by the VFS to read from filesystem quota file. quota_read: VFS から、ファイルシステムのクオータファイルを読むために呼ばれます。 # quota_write: called by the VFS to write to filesystem quota file. quota_write: VFS から、ファイルシステムのクオータファイルに書くために呼ばれます。 #Whoever sets up the inode is responsible for filling in the "i_op" field. This #is a pointer to a "struct inode_operations" which describes the methods that #can be performed on individual inodes. inode を設定する処理では、"i_op" フィールドを設定する責務があります。これは、各個別の inode に対して実行可能なメソッドを記載した構造体 "struct inode_operations" へのポイ ンタです。 #The Inode Object #================ Inode オブジェクト ================== #An inode object represents an object within the filesystem. inode オブジェクトは、ファイルシステム内のオブジェクトを表わします。 #struct inode_operations #----------------------- #This describes how the VFS can manipulate an inode in your #filesystem. As of kernel 2.6.22, the following members are defined: ここでは、VFS がファイルシステムの inode をどのように操作するかが記載されて います。カーネル 2.6.22 では以下のメンバが定義されています。 struct inode_operations { int (*create) (struct inode *,struct dentry *,int, struct nameidata *); struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); int (*link) (struct dentry *,struct inode *,struct dentry *); int (*unlink) (struct inode *,struct dentry *); int (*symlink) (struct inode *,struct dentry *,const char *); int (*mkdir) (struct inode *,struct dentry *,int); int (*rmdir) (struct inode *,struct dentry *); int (*mknod) (struct inode *,struct dentry *,int,dev_t); int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char __user *,int); void * (*follow_link) (struct dentry *, struct nameidata *); void (*put_link) (struct dentry *, struct nameidata *, void *); void (*truncate) (struct inode *); int (*permission) (struct inode *, int, struct nameidata *); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); void (*truncate_range)(struct inode *, loff_t, loff_t); }; #Again, all methods are called without any locks being held, unless #otherwise noted. くりかえしますが、すべてのメソッドは、特に注記なき限りどのロックも持たずに呼び 出し可能です。 # create: called by the open(2) and creat(2) system calls. Only # required if you want to support regular files. The dentry you # get should not have an inode (i.e. it should be a negative # dentry). Here you will probably call d_instantiate() with the # dentry and the newly created inode create: open(2) および creat(2) システムコールから呼ばれます。通常のファ イルをサポートしたい場合だけ必要です。得られた dnetry には inode は 含まれていないはずです (つまり、負の dentry のはずです)。ここで恐らく dentry と新規に作成した inode を引数にして、d_instantiate() を呼ぶこと になるでしょう。 # lookup: called when the VFS needs to look up an inode in a parent # directory. The name to look for is found in the dentry. This # method must call d_add() to insert the found inode into the # dentry. The "i_count" field in the inode structure should be # incremented. If the named inode does not exist a NULL inode # should be inserted into the dentry (this is called a negative # dentry). Returning an error code from this routine must only # be done on a real error, otherwise creating inodes with system # calls like create(2), mknod(2), mkdir(2) and so on will fail. # If you wish to overload the dentry methods then you should # initialise the "d_dop" field in the dentry; this is a pointer # to a struct "dentry_operations". # This method is called with the directory inode semaphore held lookup: VFS が親ディレクトリ内の inode を検索する必要がある場合に呼ばれます。 探すべき名前は dentry に格納されています。このメソッドは、見つかった inode を dentry に挿入するため d_add() を呼ばなければいけません。 inode 構造体の "i_count" フィールドは +1 すべきです。名前で指定 された inode が存在しない場合、dentry には NULL の inode が挿入さ れるようにすべきです (これを負の dentry と言います)。このルーチン からエラーを返すのは、本当のエラーの場合のみにしなければいけません。 そうしなければ、create(2), mknod(2), mkdir(2) などを使った inode の作成が失敗するようになります。dentry メソッドをオーバライドした い場合には、dentry の d_dop フィールドを初期化すべきです。このフィ ールドは dentry_operations 構造体へのポインタです。 このメソッドはディレクトリ inode セマフォアを持った状態で呼ばなければいけません。 # link: called by the link(2) system call. Only required if you want # to support hard links. You will probably need to call # d_instantiate() just as you would in the create() method link: link(2) システムコールから呼ばれます。ハードリンクをサポートしたい 場合にのみ必要です。create() メソッド同様に、ここで d_instantiate() を呼ぶ必要が恐らくあるでしょう。 # unlink: called by the unlink(2) system call. Only required if you # want to support deleting inodes unlink: unlink(2) システムコールから呼ばれます。inode の削除をサポートし たい場合にのみ必要です。 # symlink: called by the symlink(2) system call. Only required if you # want to support symlinks. You will probably need to call # d_instantiate() just as you would in the create() method symlink: symlink(2) システムコールから呼ばれます。シンボリックリンクをサ ポートしたい場合にのみ必要です。create() メソッド同様に、ここで d_instantiate() を呼ぶ必要が恐らくあるでしょう。 # mkdir: called by the mkdir(2) system call. Only required if you want # to support creating subdirectories. You will probably need to # call d_instantiate() just as you would in the create() method mkdir: mkdir(2) システムコールから呼ばれます。サブディレクトリの作成をサ ポートしたい場合にのみ必要です。create() メソッド同様に、ここで d_instantiate() を呼ぶ必要が恐らくあるでしょう。 # rmdir: called by the rmdir(2) system call. Only required if you want # to support deleting subdirectories rmdir: rmdir(2) システムコールから呼ばれます。サブディレクトリの削除をサ ポートしたい場合にのみ必要です。 # mknod: called by the mknod(2) system call to create a device (char, # block) inode or a named pipe (FIFO) or socket. Only required # if you want to support creating these types of inodes. You # will probably need to call d_instantiate() just as you would # in the create() method mknod: mknod(2) システムコールから呼ばれ、デバイス (char, block) inode や、名前付きパイプ (FIFO) や、ソケットを作成します。これらの種類の inode をサポートしたい場合にのみ必要です。create() メソッド同様に、 ここで d_instantiate() を呼ぶ必要が恐らくあるでしょう。 # rename: called by the rename(2) system call to rename the object to # have the parent and name given by the second inode and dentry. rename: rename(2) システムコールから呼ばれ、オブジェクトを、二番目の inode と dentry で与えられた親と名前を持つように変更します。 # readlink: called by the readlink(2) system call. Only required if # you want to support reading symbolic links readlink: readlink(2) システムコールから呼ばれます。シンボリックリンクの 読み出しをサポートしたい場合にのみ必要です。 # follow_link: called by the VFS to follow a symbolic link to the # inode it points to. Only required if you want to support # symbolic links. This method returns a void pointer cookie # that is passed to put_link(). follow_link: VFS が、シンボリックリンクの指している inode へ辿る際に呼 ばれます。シンボリックリンクをサポートしたい場合にのみ必要です。こ のメソッドは void ポインタクッキーを返し、それが put_link() に渡さ れます。 # put_link: called by the VFS to release resources allocated by # follow_link(). The cookie returned by follow_link() is passed # to this method as the last parameter. It is used by # filesystems such as NFS where page cache is not stable # (i.e. page that was installed when the symbolic link walk # started might not be in the page cache at the end of the # walk). put_link: VFS が、follow_link() によって割り当てたリソースを解放する際 に呼ばれます。follow_link() から返されたクッキーがこのメソッドに最 後のパラメータとして渡されます。このメソッドは NFS などのページキャ ッシュの内容が変化する (つまり、シンボリックリンクを辿る処理を開始 した際にインストールしたページが、辿る処理が終了した時にページキャ ッシュ内に存在しないかも知れないような) ファイルシステムで使われま す。 # truncate: called by the VFS to change the size of a file. The # i_size field of the inode is set to the desired size by the # VFS before this method is called. This method is called by # the truncate(2) system call and related functionality. truncate: VFS が、ファイルのサイズを変更する際に呼ばれます。inode の i_size フィールドは、このメソッドが呼ばれる前に VFS により望ましい 値に設定されます。このメソッドは truncate(2) システムコールとその関 連機能から呼ばれます。 # permission: called by the VFS to check for access rights on a POSIX-like # filesystem. permission: VFS が、POSIX 互換のファイルシステムのアクセス権限をチェッ クする際に呼ばれます。 # setattr: called by the VFS to set attributes for a file. This method # is called by chmod(2) and related system calls. setattr: VFS が、ファイルのアトリビュートを変更する際に呼ばれます。 chmod(2) システムコールとその関連システムコールから呼ばれます。 # getattr: called by the VFS to get attributes of a file. This method # is called by stat(2) and related system calls. getattr: VFS が、ファイルのアトリビュートを読む際に呼ばれます。stat(2) システムコールとその関連システムコールから呼ばれます。 # setxattr: called by the VFS to set an extended attribute for a file. # Extended attribute is a name:value pair associated with an # inode. This method is called by setxattr(2) system call. setxattr: VFS から、ファイルの拡張アトリビュートを変更する際に呼ばれます。 拡張アトリビュートとは、inode に関連づけられた 名前:値 のペアです。 setxattr(2) システムコールから呼ばれます。 # getxattr: called by the VFS to retrieve the value of an extended # attribute name. This method is called by getxattr(2) function # call. getxattr: VFS から、ファイルの拡張アトリビュート名に対する値を取得する際に 呼ばれます。getxattr(2) 関数コールから呼ばれます。 # listxattr: called by the VFS to list all extended attributes for a # given file. This method is called by listxattr(2) system call. listxattr: VFS から、指定ファイルの全拡張アトリビュートを並べ上げる際に呼 ばれます。listxattr(2) システムコールから呼ばれます。 # removexattr: called by the VFS to remove an extended attribute from # a file. This method is called by removexattr(2) system call. removexattr: VFS から、指定ファイルの (一つの) 拡張アトリビュートを削除す るために呼ばれます。removexattr(2) システムコールから呼ばれます。 # truncate_range: a method provided by the underlying filesystem to truncate a # range of blocks , i.e. punch a hole somewhere in a file. truncate_range: 下層のファイルシステムで提供された、ブロックの範囲を切り つめるメソッド、つまりファイルの何処かに穴を穿つメソッドです。 #The Address Space Object #======================== アドレス空間オブジェクト ======================== #The address space object is used to group and manage pages in the page #cache. It can be used to keep track of the pages in a file (or #anything else) and also track the mapping of sections of the file into #process address spaces. アドレス空間オブジェクトは、ページキャッシュ内のページをグループ化し、管理 するために用います。これはファイル (またはそれ以外の何でも) 内のページの履 歴を追跡するために用いることができ、ファイルのプロセスアドレス空間へのセク ションマッピングを追跡するのにも使えます。 #There are a number of distinct yet related services that an #address-space can provide. These include communicating memory #pressure, page lookup by address, and keeping track of pages tagged as #Dirty or Writeback. アドレス空間で提供される、異なってはいるが関連したサービスがいくつかありま す。これらにはメモリ消費量の把握と管理、アドレスによるページの検索、Dirty や Writeback とタグ付けられたページの履歴を保持するなどがあります。 #The first can be used independently to the others. The VM can try to #either write dirty pages in order to clean them, or release clean #pages in order to reuse them. To do this it can call the ->writepage #method on dirty pages, and ->releasepage on clean pages with #PagePrivate set. Clean pages without PagePrivate and with no external #references will be released without notice being given to the #address_space. 最初のものは他のものとは独立に使用できます。VM は Dirty なページを clean にするために 書き戻すことができますし、再利用のため Clean なページをリリースすることもできます。 /* 訳注:ここでのリリースは解放ではなく、要求元に渡すこと */ これら処理を行なうため、VM は ->writepage メソッドを Dirty ページに対して呼ぶ こともできますし、PagePrivate をセットした Clean なページに ->releasepage メソッドを呼ぶこともできます。PagePrivate がセットされて いない Clean なページで、外部参照のないものは、対象となるアドレス空間に通知 を行なわずにリリースされます。 #To achieve this functionality, pages need to be placed on an LRU with #lru_cache_add and mark_page_active needs to be called whenever the #page is used. この機能を実現するため、ページは lru_cache_add を使って LRU に配置される 必要があり、またページを使う際には mark_page_active を呼ぶ必要があります。 #Pages are normally kept in a radix tree index by ->index. This tree #maintains information about the PG_Dirty and PG_Writeback status of #each page, so that pages with either of these flags can be found #quickly. ページは通常 ->index から指される Radix tree の index に格納されます。このツリー は、各ページの PG_Dirty と PG_Writeback 状態情報を保持しますので、この何れかのフラグ を持ったページを素早く発見できます。 #The Dirty tag is primarily used by mpage_writepages - the default #->writepages method. It uses the tag to find dirty pages to call #->writepage on. If mpage_writepages is not used (i.e. the address #provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is #almost unused. write_inode_now and sync_inode do use it (through #__sync_single_inode) to check if ->writepages has been successful in #writing out the whole address_space. Dirty タグの第一の目的は mpage_writepages での使用です。 これは標準の ->writepages メソッドです。このメソッドでは ->writepage を実行すべき Dirty なページをタグを使って探します。mpage_writepages が使われない場合 (つ まり、そのアドレスが自前の ->writepages メソッドを持つ場合) 、 PAGECACHE_TAG_DIRTY タグはほとんど使用されません。ただし、write_inode_now と sync_inode は、->writepages がアドレス空間の全体の書き出しに成功した かどうかのチェックにこのタグを使用します (__sync_single_inode 経由で) 。 #The Writeback tag is used by filemap*wait* and sync_page* functions, #via filemap_fdatawait_range, to wait for all writeback to #complete. While waiting ->sync_page (if defined) will be called on #each page that is found to require writeback. Writeback タグは、wait_on_page_writeback_range 経由の filemap*wait* と sync_page* 関 数で、 すべての writeback が完了するのを待つのに使われます。待っている間、writeback が必要で あると判断された各ページに対して ->sync_page が (定義されている場合は) 呼ばれます。 #An address_space handler may attach extra information to a page, #typically using the 'private' field in the 'struct page'. If such #information is attached, the PG_Private flag should be set. This will #cause various VM routines to make extra calls into the address_space #handler to deal with that data. address_space ハンドラは、ページに対する追加情報を添付してもかまいません。 これには通常は 'struct page' の 'private' フィールドを使います。そのよう な情報を添付する場合には、PG_Private フラグをセットすべきです。このフラグに より、様々な VM ルーチンが、このようなデータの操作のための追加の address_space ハンドラの追加の呼び出しを行なうようになります。 #An address space acts as an intermediate between storage and #application. Data is read into the address space a whole page at a #time, and provided to the application either by copying of the page, #or by memory-mapping the page. #Data is written into the address space by the application, and then #written-back to storage typically in whole pages, however the #address_space has finer control of write sizes. アドレス空間は、アプリケーションとディスクの間を取り持つものとして動作しま す。データはアドレス空間に一回でページサイズ分読み込まれ、アプリケーション にはページのコピーを渡すか、ページをメモリマップして渡します。 データはアプリケーションによりアドレス空間に書き込まれ、ディスクに通常ペー ジ丸ごとの単位で書き戻されますが、アドレス空間自体は書き込みサイズのもう少 し細かい制御を持っています。 #The read process essentially only requires 'readpage'. The write #process is more complicated and uses write_begin/write_end or #set_page_dirty to write data into the address_space, and writepage, #sync_page, and writepages to writeback data to storage. read プロセスには、本質的には readpage だけが必要です。書き込みプロセスは もっと複雑で、prepare_write/commit_write または set_page_dirty をデータを アドレス空間に書くのに用い、writepage, sync_page と writepagesをディスクに データを書き戻すために使用します。 #Adding and removing pages to/from an address_space is protected by the #inode's i_mutex. アドレス空間にページを追加・削除する処理は inode の i_mutex で保護されて います。 #When data is written to a page, the PG_Dirty flag should be set. It #typically remains set until writepage asks for it to be written. This #should clear PG_Dirty and set PG_Writeback. It can be actually #written at any point after PG_Dirty is clear. Once it is known to be #safe, PG_Writeback is cleared. ページにデータが書き込まれたら、PG_Dirty フラグがセットされます。このフラ グは通常は writepage から書き出しが指示されるまでセットされたままです。書 き出し指示により PG_Dirty がクリアされ、PG_Writeback がセットされます。 実際は、PG_Dirty がクリアされた後、どの時点で実際の書き込みが実施されるか は予測できません。安全であるということがわかったなら、PG_Writeback がクリ アされます。 #Writeback makes use of a writeback_control structure... Writeback には writeback_control 構造体を用います。 #struct address_space_operations #------------------------------- struct address_space_operations ------------------------------- #This describes how the VFS can manipulate mapping of a file to page cache in #your filesystem. As of kernel 2.6.22, the following members are defined: ここでは VFS がファイルとページキャッシュとのマッピングを、対象のファイル システムでどのように扱うかを解説しています。カーネル 2.6.22 では以下のメ ンバが定義されています。 struct address_space_operations { int (*writepage)(struct page *page, struct writeback_control *wbc); int (*readpage)(struct file *, struct page *); int (*sync_page)(struct page *); int (*writepages)(struct address_space *, struct writeback_control *); int (*set_page_dirty)(struct page *page); int (*readpages)(struct file *filp, struct address_space *mapping, struct list_head *pages, unsigned nr_pages); int (*write_begin)(struct file *, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata); int (*write_end)(struct file *, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata); sector_t (*bmap)(struct address_space *, sector_t); int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov, loff_t offset, unsigned long nr_segs); struct page* (*get_xip_page)(struct address_space *, sector_t, int); /* migrate the contents of a page to the specified target */ int (*migratepage) (struct page *, struct page *); int (*launder_page) (struct page *); int (*error_remove_page) (struct mapping *mapping, struct page *page); }; # writepage: called by the VM to write a dirty page to backing store. # This may happen for data integrity reasons (i.e. 'sync'), or # to free up memory (flush). The difference can be seen in # wbc->sync_mode. # The PG_Dirty flag has been cleared and PageLocked is true. # writepage should start writeout, should set PG_Writeback, # and should make sure the page is unlocked, either synchronously # or asynchronously when the write operation completes. writepage: VM から Dirty ページをバッキングストアに書き込むために呼ばれ ます。これはデータの整合性を取るため (例 'sync')、またはメモリを解 放する (flush) ためなどで実行されます。この違いは wbc->sync_mode で 見ることができます。PG_Dirty フラグはクリアされ、PageLocked は真に なります。writepage は書き出しを開始し、PG_Writeback をセットし、書 き込み処理終了時に、同期的な場合にも非同期な場合にも、ページがロック されていないように確認すべきです。 # If wbc->sync_mode is WB_SYNC_NONE, ->writepage doesn't have to # try too hard if there are problems, and may choose to write out # other pages from the mapping if that is easier (e.g. due to # internal dependencies). If it chooses not to start writeout, it # should return AOP_WRITEPAGE_ACTIVATE so that the VM will not keep # calling ->writepage on that page. もしwbc->sync_mode が WB_SYNC_NONE ならば、->writepage は問題 がある場合に強くは処理を進める必要はなく、他のより易しいページの書 き出しを選択してもかまいません (内部の依存関係などの理由により)。 書き出しを行なわないと決めたなら、AOP_WRITEPAGE_ACTIVATE を返して、 VM がこのページに ->writepage を呼び続けることがないようにすべき です。 # See the file "Locking" for more details. 詳細は "Locking" ファイルを参照ください。 # readpage: called by the VM to read a page from backing store. # The page will be Locked when readpage is called, and should be # unlocked and marked uptodate once the read completes. # If ->readpage discovers that it needs to unlock the page for # some reason, it can do so, and then return AOP_TRUNCATED_PAGE. # In this case, the page will be relocated, relocked and if # that all succeeds, ->readpage will be called again. readpage: VM により、ページをバッキングストアから読み込むために呼ばれます。 readpage を呼ぶ時点でページはロックしておき、読み出しが終了したなら ロックを解除して uptodate とマークするべきです。 /* 訳注:ここだけを読むと readpage 内でロックするように読めるのだが、後ろの記載と合わ ない */ もし ->readpage が何らかの理由でページをアンロックする必要があ る場合は、アンロックを行ない、AOP_TRUNCATED_PAGE を返します。この場 合には、ページを再配置し、再度ロックを取得します。この処理が問題なく成功した場合に は、この後 ->readpage を再度呼び出します。 # sync_page: called by the VM to notify the backing store to perform all # queued I/O operations for a page. I/O operations for other pages # associated with this address_space object may also be performed. sync_page: バッキングストア (スワップ) に対して、キューイングされた I/O 処理をすべて実行するよう知らせるために、VM から呼ばれます。この address_space オブジェクトに関連づけられた、他のページに対する I/O 操作も同時に実行してかまいません。 # This function is optional and is called only for pages with # PG_Writeback set while waiting for the writeback to complete. この関数はオプションで、writeback の終了を待つ間 PG_Writeback タグ がセットされたページに対して呼ばれます。 # writepages: called by the VM to write out pages associated with the # address_space object. If wbc->sync_mode is WBC_SYNC_ALL, then # the writeback_control will specify a range of pages that must be # written out. If it is WBC_SYNC_NONE, then a nr_to_write is given # and that many pages should be written if possible. # If no ->writepages is given, then mpage_writepages is used # instead. This will choose pages from the address space that are # tagged as DIRTY and will pass them to ->writepage. writepages: アドレス空間オブジェクトに関連づけられたページを書き出すため、 VM から呼ばれます。もし wbc->sync_mode が WBC_SYNC_ALL の場合、 writeback_control は書き出さなければならないページの範囲を指定しま す。もし WBC_SYNC_NONE の場合には、nr_to_write が与えられているので、可能な 場合はその数のページを書き込むべきです。もし ->writepages が提 供されていない場合は、代わりに mpage_writepages が使われます。これ により、DIRTY とタグ付けされたページがアドレス空間から選択され、 ->writepage に渡されます。 # set_page_dirty: called by the VM to set a page dirty. # This is particularly needed if an address space attaches # private data to a page, and that data needs to be updated when # a page is dirtied. This is called, for example, when a memory # mapped page gets modified. # If defined, it should set the PageDirty flag, and the # PAGECACHE_TAG_DIRTY tag in the radix tree. set_page_dirty: ページを Dirty にするために VM から呼ばれます。これは特 にアドレス空間がプライベートデータをページに付けていて、そのペー ジに書き込みを行ったためにそのデータを更新しなければいけない場合 に必要になります。このメソッドは、例えばメモリマップされたページ が変更された場合に呼ばれます。定義されている場合には、Radix tree 内の PageDirty フラグと Radix 中の PAGECHACHE_TAG_DIRTY タグをセ ットすべきです。 # readpages: called by the VM to read pages associated with the address_space # object. This is essentially just a vector version of # readpage. Instead of just one page, several pages are # requested. # readpages is only used for read-ahead, so read errors are # ignored. If anything goes wrong, feel free to give up. readpages: アドレス空間オブジェクトに関連づけられたページを読むため、VM から呼ばれます。これは基本的には、readpage のベクトル版です。一つ のページの代わりに、複数のページを要求するためのものです。 readpages は先読みのためにのみ用いられますので、読み込みエラー は無視されます。何かがうまくいかなかったら、あきらめてもかまい ません。 write_begin: # Called by the generic buffered write code to ask the filesystem to # prepare to write len bytes at the given offset in the file. The # address_space should check that the write will be able to complete, # by allocating space if necessary and doing any other internal # housekeeping. If the write will update parts of any basic-blocks on # storage, then those blocks should be pre-read (if they haven't been # read already) so that the updated blocks can be written out properly. 汎用のバッファ付き書き込みコードから、ファイルの offset で指定され た位置から len バイトの書き込みができるよう、ファイルシステムに準備 をさせるために呼ばれます。 アドレス空間は、書き込みが完了できるよう チェックし、必要な空間を割り当てることや、その他の内部管理処理を実 行します。書き込みがディスクの基本ブロックの一部を更新する場合には、 更新のブロック書き込みが適切に行なわれるようこれらのブロックを pre-read 状態に (すでにそうなっていない場合には) します。 # The filesystem must return the locked pagecache page for the specified # offset, in *pagep, for the caller to write into. ファイルシステムは、呼び出し元が書き込みを行なえるよう、指定オフセ ットのページキャッシュ内ページをロックされた状態で *pagep に返さな ければいけません # It must be able to cope with short writes (where the length passed to # write_begin is greater than the number of bytes copied into the page). この処理は短い書き込み (write_begin に渡された長さがページ内にコピ ーされたバイト数より大きい場合) を処理できなければいけません。 # flags is a field for AOP_FLAG_xxx flags, described in # include/linux/fs.h. flags は、include/linux/fs.h で記載されている AOP_FLAG_xxx フラ グを指定するためのフィールドです。 # A void * may be returned in fsdata, which then gets passed into # write_end. fsdata には void * 値を戻すことができ、その値は次に write_end に 渡されます。 # Returns 0 on success; < 0 on failure (which is the error code), in # which case write_end is not called. 成功した場合 0 を返します。また失敗の場合 < 0 (これはエラーコー ドの値になります) を返します。失敗の場合には write_end は呼びません。 # write_end: After a successful write_begin, and data copy, write_end must # be called. len is the original len passed to write_begin, and copied # is the amount that was able to be copied (copied == len is always true # if write_begin was called with the AOP_FLAG_UNINTERRUPTIBLE flag). write_end: write_begin と data copy が成功裏に終了した後では、write_end を呼ばなければいけません。len は write_begin に渡した元々の値で、 copied は実際にコピーできた量です (write_begin が AOP_FLAG_UNINTERRUPTIBLE 付きで呼ばれていた場合には常に copied == len になります)。 # The filesystem must take care of unlocking the page and releasing it # refcount, and updating i_size. ファイルシステム側でページのロックの解除、参照カウントの解放、i_size の更新の面倒は見なければいけません。 # Returns < 0 on failure, otherwise the number of bytes (<= 'copied') # that were able to be copied into pagecache. 失敗した場合 0 を返し、それ以外の場合にはページキャッシュに書き込む ことができたバイト数 (<= 'copied') を返します。 # bmap: called by the VFS to map a logical block offset within object to # physical block number. This method is used by the FIBMAP # ioctl and for working with swap-files. To be able to swap to # a file, the file must have a stable mapping to a block # device. The swap system does not go through the filesystem # but instead uses bmap to find out where the blocks in the file # are and uses those addresses directly. bmap: VFS により、オブジェクト内の 論理ブロック offset 値を物理ブロック番 号に対応付けるために呼ばれます。このメソッドは FIBMAP ioctl と、 swap ファイル操作で使います。ファイルに対してスワップを行なうために は、ファイルはブロックデバイスで固定のマッピングを持っている必要が あります。スワップシステムはファイルシステムを用いず、bmap を使って ファイル内のブロックがどこにあるかを見つけ出して、そのアドレスを直 に使います。 # invalidatepage: If a page has PagePrivate set, then invalidatepage # will be called when part or all of the page is to be removed # from the address space. This generally corresponds to either a # truncation or a complete invalidation of the address space # (in the latter case 'offset' will always be 0). # Any private data associated with the page should be updated # to reflect this truncation. If offset is 0, then # the private data should be released, because the page # must be able to be completely discarded. This may be done by # calling the ->releasepage function, but in this case the # release MUST succeed. invalidatepage: ページに PagePrivate が設定されていた場合、そのページの 一部または全部をアドレス空間から削除する場合に invalidatepage が呼 ばれます。これは通常切りつめか、アドレス空間の完全な無効化 (この場 合 offset は常に 0 になります) のどちらかになります。この切りつめ を反映するよう、ページに付随するプライベートデータは更新すべきです。 offset が 0 の場合、ページを完全に捨て去ることができなければならな いため、プライベートデータは解放 (放棄) すべきです。この処理を ->releasepage 関数を呼ぶことによって行なうことは可能ですが、そ の場合にはリリースは成功しなければ*いけません*。 # releasepage: releasepage is called on PagePrivate pages to indicate # that the page should be freed if possible. ->releasepage # should remove any private data from the page and clear the # PagePrivate flag. It may also remove the page from the # address_space. If this fails for some reason, it may indicate # failure with a 0 return value. # This is used in two distinct though related cases. The first # is when the VM finds a clean page with no active users and # wants to make it a free page. If ->releasepage succeeds, the # page will be removed from the address_space and become free. releasepage: releasepage は PagePrivate ページに対して、可能ならばこのペ ージを解放すべきであることを示すために用います。->releasepageは ページのプライベートデータを全て削除し、 PagePrivate フラグをクリ アすべきです。その際、アドレス空間からページを削除する処理を行って も構いません。 何らかの理由で処理が失敗した場合、戻り値 0 で失敗を示します。 この処理は関連してはいるが二つの異なった場合に使われます。最初の場 合は、VM が利用者のいない Clean なページを見つけて、それをフリーペ ージとしたい場合です。->releasepage が成功した場合、ページはア ドレス空間から削除されてフリーになります。 # The second case is when a request has been made to invalidate # some or all pages in an address_space. This can happen # through the fadvice(POSIX_FADV_DONTNEED) system call or by the # filesystem explicitly requesting it as nfs and 9fs do (when # they believe the cache may be out of date with storage) by # calling invalidate_inode_pages2(). # If the filesystem makes such a call, and needs to be certain # that all pages are invalidated, then its releasepage will # need to ensure this. Possibly it can clear the PageUptodate # bit if it cannot free private data yet. 二番目の場合は、要求によりアドレス空間内の一部あるいは全てのページ を無効化する場合です。 このような処理は fadvice(POSIX_FADV_DONTNEED) システムコールか、ファイルシステムが nfs や 9fs のように明示的に invalidate_inode_pages2() を読んで無効化を要求した場合 (これらのフ ァイルシステムがキャッシュがストレージに対して古くなってしまってい ると判断した場合) に発生します。ファイルシステムがこのような呼び出 しを行なった場合、そして全てのページが無効化されたことを保証する必 要がある場合、その処理での releasepage がそれを保証しなければいけま せん。プライベートデータをクリアできない間は、恐らく PageUptodate ビットをクリアすることになるでしょう。 # direct_IO: called by the generic read/write routines to perform # direct_IO - that is IO requests which bypass the page cache # and transfer data directly between the storage and the # application's address space. direct_IO: 共用の read/write ルーチンから direct_IO (ページキャッシュを バイパスした、ストレージとアプリケーションのアドレス空間との間で直 接データをやりとりする I/O 処理) を行なう場合に呼ばれます。 # get_xip_page: called by the VM to translate a block number to a page. # The page is valid until the corresponding filesystem is unmounted. # Filesystems that want to use execute-in-place (XIP) need to implement # it. An example implementation can be found in fs/ext2/xip.c. get_xip_page: ブロック番号をページ番号に変換するために、VM から呼ばれます。 このページ番号は対象ファイルシステムがアンマウントされるまでは有効です。 execute-in-place (XIP) を使いたいファイルシステムは、このメソッド を実装する必要があります。参考実装が fs/ext2/xip.c にあります。 # migrate_page: This is used to compact the physical memory usage. # If the VM wants to relocate a page (maybe off a memory card # that is signalling imminent failure) it will pass a new page # and an old page to this function. migrate_page should # transfer any private data across and update any references # that it has to the page. migrate_page: これは物理メモリ消費量を減少させるために使います。もし VM がページを再配置したい (例えば緊急のエラーを報告したメモリカードか ら外したい) 場合は、新しいページと古いページがこの関数に渡されます。 migrate_page は全てのプライベートデータを移動し、ページに対しての参 照を更新すべきです。 # launder_page: Called before freeing a page - it writes back the dirty page. To # prevent redirtying the page, it is kept locked during the whole # operation. launder_page: ページを解放する前に呼ばれます − つまり Dirty ページを書き戻しま す。ページが再度 Dirty になるのを防ぐため、操作の間ずっとページがロ ックされます。 # error_remove_page: normally set to generic_error_remove_page if truncation # is ok for this address space. Used for memory failure handling. # Setting this implies you deal with pages going away under you, # unless you have them locked or reference counts increased. error_remove_page: 当該アドレス空間に対して切り詰めが可能な場合、通常は generic_error_remove_page に設定されます。メモリ障害処理で使われま す。このフラグを設定することは、ロックをかけておらず、参照カウント を増やしてもいない場合、管理下のページが失われる場合を扱えることを 意味します。 #The File Object #=============== ファイルオブジェクト ==================== #A file object represents a file opened by a process. ファイルオブジェクトは、プロセスによって open されているファイルに対応 します。 #struct file_operations #---------------------- struct file_operations ---------------------- #This describes how the VFS can manipulate an open file. As of kernel #2.6.22, the following members are defined: 以下は VFS が開かれているファイルをどのように操作するかを記載します。カー ネル 2.6.22 では以下のメンバが定義されています。 struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); }; #Again, all methods are called without any locks being held, unless #otherwise noted. 再度記載しますが、すべてのメソッドは、特に注記なき限りロックを持たずに呼び出し可能です。 # llseek: called when the VFS needs to move the file position index llseek: VFS が、ファイル位置インデックスを動かす際に呼ばれます。 # read: called by read(2) and related system calls read: read(2) および関連のシステムコールから呼ばれます。 # aio_read: called by io_submit(2) and other asynchronous I/O operations aio_read: io_submit(2) および関連非同期 I/O 処理から呼ばれます。 # write: called by write(2) and related system calls write: write(2) および関連のシステムコールから呼ばれます。 # aio_write: called by io_submit(2) and other asynchronous I/O operations aio_write: io_submit(2) および関連非同期 I/O 処理から呼ばれます。 # readdir: called when the VFS needs to read the directory contents readdir: VFS がディレクトリコンテンツを読む必要があるとき呼ばれます。 # poll: called by the VFS when a process wants to check if there is # activity on this file and (optionally) go to sleep until there # is activity. Called by the select(2) and poll(2) system calls poll: あるプロセスが対象ファイルに対して動作/処理があるかどうかのチェ ックをしたい場合、そして (オプションとして) 処理が起きるまでスリ ープに移行したい場合に、VFS から呼ばれます。 select(2) および poll(2) システムコールから呼ばれます。 # ioctl: called by the ioctl(2) system call ioctl: ioctl(2) システムコールから呼ばれます。 # unlocked_ioctl: called by the ioctl(2) system call. Filesystems that do not # require the BKL should use this method instead of the ioctl() above. unlocked_ioctl: ioctl(2) システムコールから呼ばれます。BKL を必要としな いファイルシステムでは、上の ioctl() ではなくこのメソッドを使ってく ださい。 # compat_ioctl: called by the ioctl(2) system call when 32 bit system calls # are used on 64 bit kernels. compat_ioctl: 64bit カーネルで 32bit システムコールが使われたとき、 ioctl(2) システムコールから呼ばれます。 # mmap: called by the mmap(2) system call mmap: mmap(2) システムコールから呼ばれます。 # open: called by the VFS when an inode should be opened. When the VFS # opens a file, it creates a new "struct file". It then calls the # open method for the newly allocated file structure. You might # think that the open method really belongs in # "struct inode_operations", and you may be right. I think it's # done the way it is because it makes filesystems simpler to # implement. The open() method is a good place to initialize the # "private_data" member in the file structure if you want to point # to a device structure open: VFS が inode をオープンすべきと判断したときに呼ばれます。VFS がファ イルをオープンした場合、VFS は新たな file 構造体を作成します。次に VFS は、新たに割り当てられたファイル構造体の open メソッドを呼びます。 このメソッドは "struct inode_operations" にあるほうがいいと感じら れるかも知れませんが、その印象は恐らく正しいでしょう。これが現状こ のようになっているのは、ファイルシステムの実装がより簡単になるため だと考えています。open() メソッドは、ファイル構造体の "private_data" メンバがデバイス構造体を指すようにしたいなら、そのように初期化するの に良い場所です。 # flush: called by the close(2) system call to flush a file flush: close(2) システムコールにより、ファイルをフラッシュするために呼ば れます。 # release: called when the last reference to an open file is closed release: 開いているファイルの最後の参照が閉じられた際に呼ばれます。 # fsync: called by the fsync(2) system call fsync: fsync(2) システムコールから呼ばれます。 # fasync: called by the fcntl(2) system call when asynchronous # (non-blocking) mode is enabled for a file fasync: 非同期 (ノンブロッキング) モードをファイルに対して有効とする fcntl(2) システムコールで呼ばれます。 # lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW # commands lock: fcntl(2) で F_GETLK, F_SETLK, と F_SETLKW コマンドの際に呼ばれます。 # readv: called by the readv(2) system call readv: readv(2) システムコールから呼ばれます。 # writev: called by the writev(2) system call writev: writev(2) システムコールから呼ばれます。 # sendfile: called by the sendfile(2) system call sendfile: sendfile(2) システムコールから呼ばれます。 # get_unmapped_area: called by the mmap(2) system call get_unmapped_area: mmap(2) システムコールから呼ばれます。 # check_flags: called by the fcntl(2) system call for F_SETFL command check_flags: fcntl(2) で、 F_SETFL コマンドの場合に呼ばれます。 # flock: called by the flock(2) system call flock: flock(2) システムコールから呼ばれます。 # splice_write: called by the VFS to splice data from a pipe to a file. This # method is used by the splice(2) system call splice_write: VFS がパイプからファイルへのデータ splice 処理を行なうため に呼ばれます。このメソッドは splice(2) システムコールで使われます。 # splice_read: called by the VFS to splice data from file to a pipe. This # method is used by the splice(2) system call splice_read: VFS がファイルからパイプへのデータ splice 処理を行なうため に呼ばれます。このメソッドは splice(2) システムコールで使われます。 #Note that the file operations are implemented by the specific #filesystem in which the inode resides. When opening a device node #(character or block special) most filesystems will call special #support routines in the VFS which will locate the required device #driver information. These support routines replace the filesystem file #operations with those for the device driver, and then proceed to call #the new open() method for the file. This is how opening a device file #in the filesystem eventually ends up calling the device driver open() #method. 注意: このファイル処理は、inode が存在するファイルシステム特有の実装になっ ていることに注意してください。デバイスノード (キャラクタ型またはブロック型) を開く場合、ほとんどのファイルシステムは VFS 内の特別のサポート処理を呼び出し、 必要なデバイスドライバ情報を取り出します。これらのサポート処理はファイルシ ステムのファイル処理をデバイスドライバに対するものに置き換え、ファイルに対 する新規の open() メソッドを引き続き実行します。これはファイルシステムのデ バイスファイルをオープンすることが結局 デバイスドライバの open() メソッドを 呼ぶことになる手順の種明かしです。 #Directory Entry Cache (dcache) #============================== ディレクトリエントリキャッシュ (dcache) ======================================= #struct dentry_operations #------------------------ struct dentry_operations ------------------------ #This describes how a filesystem can overload the standard dentry #operations. Dentries and the dcache are the domain of the VFS and the #individual filesystem implementations. Device drivers have no business #here. These methods may be set to NULL, as they are either optional or #the VFS uses a default. As of kernel 2.6.22, the following members are #defined: ここでは、ファイルシステムで標準 dentry 操作をどのようにしてオーバロードす ることができるかが記載されています。dentry と dcache は、VFS と個々のファ イルシステム実装の領域に属します。デバイスドライバはこの処理に関与しません。 これらのメソッドは NULL にセットしてかまいません。これらはオプションですし、 VFS は NULL の場合には標準で用意された処理を使うからです。カーネル 2.6.22 では以下のメンバが定義されています。 struct dentry_operations { int (*d_revalidate)(struct dentry *, struct nameidata *); int (*d_hash) (struct dentry *, struct qstr *); int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); int (*d_delete)(struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); char *(*d_dname)(struct dentry *, char *, int); }; # d_revalidate: called when the VFS needs to revalidate a dentry. This # is called whenever a name look-up finds a dentry in the # dcache. Most filesystems leave this as NULL, because all their # dentries in the dcache are valid d_revalidate: VFS が、dentry を再度有効化したい場合に呼ばれます。このメ ソッドは名前解決処理が dcache 内に dentry を発見した際に常に呼ばれ ます。ほとんどのファイルシステムではこのメソッドは NULL です。これ は通常のファイルシステムでは dcache 内の dentry はすべて有効になっ ているためです。 # d_hash: called when the VFS adds a dentry to the hash table d_hash: VFS が dentry をハッシュテーブルに加えたい場合に呼ばれます。 # d_compare: called when a dentry should be compared with another d_compare: dentry 同士を比較したい場合に呼ばれます。 # d_delete: called when the last reference to a dentry is # deleted. This means no-one is using the dentry, however it is # still valid and in the dcache d_delete: dentry への最後の参照が削除された場合、つまり誰も使っていない dentry が、dcache 内で依然として有効になっている場合に呼ばれます。 # d_release: called when a dentry is really deallocated d_release: dentry が本当に割り当て削除された場合に呼ばれます。 # d_iput: called when a dentry loses its inode (just prior to its # being deallocated). The default when this is NULL is that the # VFS calls iput(). If you define this method, you must call # iput() yourself d_iput: dentry が inode を失った場合に呼ばれます (割り当てを解放する直前 に)。このメソッドが未定義 (NULL) の時、既定値は「 VFS は iput() を 呼ぶ」、です。このメソッドを自分で実装する場合には、iput() は自分で 呼ばなければなりません。 # d_dname: called when the pathname of a dentry should be generated. # Useful for some pseudo filesystems (sockfs, pipefs, ...) to delay # pathname generation. (Instead of doing it when dentry is created, # it's done only when the path is needed.). Real filesystems probably # dont want to use it, because their dentries are present in global # dcache hash, so their hash should be an invariant. As no lock is # held, d_dname() should not try to modify the dentry itself, unless # appropriate SMP safety is used. CAUTION : d_path() logic is quite # tricky. The correct way to return for example "Hello" is to put it # at the end of the buffer, and returns a pointer to the first char. # dynamic_dname() helper function is provided to take care of this. d_dname: dentry のパス名を作成する際に呼ばれます。一部の疑似ファイルシス テム (sockfs, pipefs, ...) でパス名生成を遅らせるために使います (dentry が生成されたときに作成するのではなく、パスが必要になったと きにのみ実行するようにします)。.本物のファイルシステムは恐らくこの 機能は必要としないでしょう。それはそのようなファイルシステムでは dentry は大域 dcache ハッシュ内に存在するため、ハッシュは不変値とす べきだからです。ロックを保持していないので、d_dname() は適切な SMP 安全性を保証しない限り dentry 自体を変更してはいけません。 注意: d_path() の論理は実にトリッキーです。 例えば、正しい "Hello" の返し方とは、その文字列をバッファの最後に置き、最初の文字へのポイ ンタを持って戻ることです。dynamic_dname() ヘルパー関数がこの状態の 面倒を見るために提供されています。 #Example : 例: static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) { return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", dentry->d_inode->i_ino); } #Each dentry has a pointer to its parent dentry, as well as a hash list #of child dentries. Child dentries are basically like files in a #directory. 各 dentry は親 dentry へのポインタと、子 dentry 群のハッシュリストを持って います。子 dentry は基本的にはディレクトリ内のファイルのようなものです。 #Directory Entry Cache API #-------------------------- ディレクトリエントリキャッシュ API ---------------------------------- #There are a number of functions defined which permit a filesystem to #manipulate dentries: ファイルシステムから dentry の操作を許すための関数が多数定義されています。 # dget: open a new handle for an existing dentry (this just increments # the usage count) dget: 既存の dentry に新しいハンドルを開きます (使用カウントが 1 増加しま す)。 # dput: close a handle for a dentry (decrements the usage count). If # the usage count drops to 0, the "d_delete" method is called # and the dentry is placed on the unused list if the dentry is # still in its parents hash list. Putting the dentry on the # unused list just means that if the system needs some RAM, it # goes through the unused list of dentries and deallocates them. # If the dentry has already been unhashed and the usage count # drops to 0, in this case the dentry is deallocated after the # "d_delete" method is called dput: dentry のハンドルを閉じます (使用カウントが 1 減少します)。使用カウ ントが 0 に落ちた場合には、 "d_delete" メソッドが呼ばれ、その dentry が親のハッシュリストに残っている場合は、対象 dentry は未使用リスト に置かれます。未使用リストに dentry を置くということは、システムで メモリが必要な場合、dentry の未使用リストから解放がおこなわれるとい うことだけを意味します。dentry が既にハッシュから外されていて、使用カ ウントが 0 に落ちた場合には、d_delete メソッド実行後 dentry は解放 されます。 # d_drop: this unhashes a dentry from its parents hash list. A # subsequent call to dput() will deallocate the dentry if its # usage count drops to 0 d_drop: 親のハッシュリストから dentry を外します。引き続いて dput() を呼 ぶことで、使用カウントが 0 に落ちた場合には dentry が解放されます。 # d_delete: delete a dentry. If there are no other open references to # the dentry then the dentry is turned into a negative dentry # (the d_iput() method is called). If there are other # references, then d_drop() is called instead d_delete: dentry を削除します。dentry に対してオープン中の参照がなかった 場合には、dentry は負の dentry に変更されます (d_iput() メソッドが 呼ばれます)。他に参照があった場合、代わりに d_drop() が呼ばれます。 # d_add: add a dentry to its parents hash list and then calls # d_instantiate() d_add: 親のハッシュリストに dentry を加えて、d_instantiate() を呼びます。 # d_instantiate: add a dentry to the alias hash list for the inode and # updates the "d_inode" member. The "i_count" member in the # inode structure should be set/incremented. If the inode # pointer is NULL, the dentry is called a "negative # dentry". This function is commonly called when an inode is # created for an existing negative dentry d_instantiate: inode のエイリアスハッシュリストに dentry を加え、d_inode メンバを更新します。inode 構造体の i_count メンバは、新規に設定さ れるか、+1 されます。inode ポインタが NULL の場合、dentry は「負の dentry」と呼ばれます。この関数は、既存の負の dentry に inode を作 成する場合に、共通処理として呼ばれます。 # d_lookup: look up a dentry given its parent and path name component # It looks up the child of that given name from the dcache # hash table. If it is found, the reference count is incremented # and the dentry is returned. The caller must use dput() # to free the dentry when it finishes using it. d_lookup: 親とパス名を与えて dentry を検索します。これは dcache ハッシュ テーブルから、指定した名の子を探します。見つかった場合、その dentry の参照カウントを +1 し、その dentry を返します。呼び出し元では、利 用終了時には d_put() を使って dentry を解放しなければいけません。 #For further information on dentry locking, please refer to the document #Documentation/filesystems/dentry-locking.txt. dentry ロックに関する詳細な説明は、 Documentation/filesystems/dentry-locking.txt を参照ください。 #Mount Options #============= マウントオプション ================== #Parsing options #--------------- パース時のオプション -------------------- #On mount and remount the filesystem is passed a string containing a #comma separated list of mount options. The options can have either of #these forms: ファイルシステムのマウントおよび再マウントの際には、カンマで分割されたマウ ントオプションを含む文字列が渡されます。オプションは以下のどちらかの形式を 取ることができます。 option option=value #The <linux/parser.h> header defines an API that helps parse these #options. There are plenty of examples on how to use it in existing #filesystems. <linux/parser.h> ヘッダにはこれらのオプションをパースするのを助ける API が定義されています。既存のファイルシステムでこれをどのように使うかにつ いては豊富な実例があります。 #Showing options #--------------- オプションの表示 ---------------- #If a filesystem accepts mount options, it must define show_options() #to show all the currently active options. The rules are: ファイルシステムがマウントオプションを受け入れる場合、現在有効なオプション の全てを表示する show_options() を定義しなければいけません。規則は以下の通 りです。 # - options MUST be shown which are not default or their values differ # from the default - 既定値では設定されないオプションと、既定値が現在の値と違うオプション は*必ず*表示しなければいけません。 # - options MAY be shown which are enabled by default or have their # default value - 既定値で有効なオプション、または現在の値が既定値と同じものの表示は任 意です。 #Options used only internally between a mount helper and the kernel #(such as file descriptors), or which only have an effect during the #mounting (such as ones controlling the creation of a journal) are exempt #from the above rules. マウントヘルパとカーネルとの間のみで内部的にのみ使うオプション (例えばファ イルディスクリプタ)、またはマウント処理時にのみ効果のあるオプション (ジャー ナル作成の制御を行なうものなど) は上記の規則の例外です。 #The underlying reason for the above rules is to make sure, that a #mount can be accurately replicated (e.g. umounting and mounting again) #based on the information found in /proc/mounts. これらの規則の背景にある理由は、/proc/mounts にある情報を使ってマウントを 正確に繰り返す (即ち、アンマウントしてマウントする) ことができることを保証 することにあります。 #A simple method of saving options at mount/remount time and showing #them is provided with the save_mount_options() and #generic_show_options() helper functions. Please note, that using #these may have drawbacks. For more info see header comments for these #functions in fs/namespace.c. mount/remount 時にオプションを待避して、それらを見せるという単純な方法は、 save_mount_options() と generic_show_options() ヘルパー関数で提供されてい ます。これらを使うことには (利点とともに) 欠点もあることにも留意してくだ さい。詳細については fs/namespace.c の関数のヘッダコメントを参照ください。 #Resources #========= リソース ======== #(Note some of these resources are not up-to-date with the latest kernel # version.) (注意: これらのリソースは必ずしも最新のカーネルバージョンに対応したもので はありません。) Creating Linux virtual filesystems. 2002 <http://lwn.net/Articles/13325/> The Linux Virtual File-system Layer by Neil Brown. 1999 <http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html> A tour of the Linux VFS by Michael K. Johnson. 1996 <http://www.tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html> A small trail through the Linux kernel by Andries Brouwer. 2001 <http://www.win.tue.nl/~aeb/linux/vfs/trail.html>
コメントが長くなった場合は、jf@listserv.linux.or.jp にお寄せください。