JF Linux Kernel 2.6 Documentation: /usr/src/linux/Documentation/filesystems/files.txt


ファイルに関するロックと構造体の管理 [プレインテキスト版]

Linux-2.6.29/Documentation/filesystems/files.txt の和訳です。
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
更新日 : 2009/05/26
翻訳者 : Seiji Kaneko < skaneko at mbn dot or dot jp >
査読者 : Masanori Kobayashi <zap03216 at nifty dot ne dot jp >
#File management in the Linux kernel
Linux カーネルでのファイル管理

#This document describes how locking for files (struct file)
#and file descriptor table (struct files) works.
この文書は、ファイル (file 構造体) のロックとファイルディスクリプタテーブ
ル (ファイル構造体) がどのように動作するかを記載したものです。

#Up until 2.6.12, the file descriptor table has been protected
#with a lock (files->file_lock) and reference count (files->count).
#->file_lock protected accesses to all the file related fields
#of the table. ->count was used for sharing the file descriptor
#table between tasks cloned with CLONE_FILES flag. Typically
#this would be the case for posix threads. As with the common
#refcounting model in the kernel, the last task doing
#a put_files_struct() frees the file descriptor (fd) table.
#The files (struct file) themselves are protected using
#reference count (->f_count).
2.6.12 まではファイルディスクリプタテーブルはロック (files->file_lock) と
リファレンスカウント (files->count) で保護され、テーブルのファイルに関す
るすべてのフィールドへのアクセスは ->file_lock で保護されていました。
また、->count が CLONE_FILES フラグつきで複製されたタスク間での、ファイル
ディスクリプタテーブルの共有に用いられていました。通常、posix スレッドが
put_files_struct() を最後に行ったタスクが、ファイルディスクリプタ (fd) 
テーブルを解放します。ファイル (struct file) 自体は、リファレンスカウント 
(->f_count) を使って保護されています。

#In the new lock-free model of file descriptor management,
#the reference counting is similar, but the locking is
#based on RCU. The file descriptor table contains multiple
#elements - the fd sets (open_fds and close_on_exec, the
#array of file pointers, the sizes of the sets and the array
#etc.). In order for the updates to appear atomic to
#a lock-free reader, all the elements of the file descriptor
#table are in a separate structure - struct fdtable.
#files_struct contains a pointer to struct fdtable through
#which the actual fd table is accessed. Initially the
#fdtable is embedded in files_struct itself. On a subsequent
#expansion of fdtable, a new fdtable structure is allocated
#and files->fdtab points to the new structure. The fdtable
#structure is freed with RCU and lock-free readers either
#see the old fdtable or the new fdtable making the update
#appear atomic. Here are the locking rules for
#the fdtable structure -
ウントによる管理は従来と同様ですが、ロック処理は RCU に基づくものになりま
す。ファイルディスクリプタテーブルには複数の要素 - fd 一式 (open_fd 群や 
close_on_exec, file ポインタの配列, 組や配列の数やサイズなど) - が格納さ
構造体 - fdtable 構造体 - 内にあります。files_struct には fdtable 構造体
へのポインタが格納され、そのポインタ経由で実際の fd テーブルへのアクセス
が行われます。もともとは fdtable は files_struct 自体に埋め込まれていま
した。それ以降の fdtable の拡張時に、新しい fdtable 構造体が導入され、
files->fdtab がこの新しい構造体を指すようになりました。fdtable 構造体は、
ロックを持たない読み出し処理から古い fdtable と新しい fdtable の両方がア
トミックに更新されているように見せることができるよう、RCU により解放され
ます。以下が fdtable 構造体へのロック取得規則です。

#1. All references to the fdtable must be done through
#   the files_fdtable() macro :
1. fdtable への参照は、必ず files_fdtable() マクロ経由で行なわなければ

	struct fdtable *fdt;


	fdt = files_fdtable(files);
	if (n <= fdt->max_fds)

#   files_fdtable() uses rcu_dereference() macro which takes care of
#   the memory barrier requirements for lock-free dereference.
#   The fdtable pointer must be read within the read-side
#   critical section.
   files_fdtable() は rcu_dereference() マクロを使います。
   rcu_dereference() マクロが、ロックなしの参照を行なうのに必要なメモリ
   バリア要求の面倒を見ます。fdtable ポインタは読み出し側のクリティカル

#2. Reading of the fdtable as described above must be protected
#   by rcu_read_lock()/rcu_read_unlock().
2. 上記の fdtable の読み出しは、rcu_read_lock()/rcu_read_unlock() で

#3. For any update to the fd table, files->file_lock must
#   be held.
3. fd テーブルを更新する場合には、どのような更新でも files->file_lock 

#4. To look up the file structure given an fd, a reader
#   must use either fcheck() or fcheck_files() APIs. These
#   take care of barrier requirements due to lock-free lookup.
#   An example :
4. ある fd に対してファイル構造体を参照するには、読み側では fcheck() ま
  たは fcheck_files() API を使わなければいけません。これらの API はロ

	struct file *file;

	file = fcheck(fd);
	if (file) {

#5. Handling of the file structures is special. Since the look-up
#   of the fd (fget()/fget_light()) are lock-free, it is possible
#   that look-up may race with the last put() operation on the
#   file structure. This is avoided using atomic_long_inc_not_zero()
#   on ->f_count :
5. ファイル構造体の操作には特別の注意が必要です。fd の検索 
  (fget()/fget_light()) はロックをとりませんから、検索時にファイル構
  造体への最後の put() 操作と競合を起こす可能性があります。これは 
  ->f_count に対して atomic_long_inc_not_zero() を用いることによっ

	file = fcheck_files(files, fd);
	if (file) {
		if (atomic_long_inc_not_zero(&file->f_count))
			*fput_needed = 1;
		/* Didn't get the reference, someone's freed */
			file = NULL;
	return file;

#   atomic_long_inc_not_zero() detects if refcounts is already zero or
#   goes to zero during increment. If it does, we fail
#   fget()/fget_light().
   atomic_long_inc_not_zero() は refcount が既に 0 となっていること、ま
   たは増加時に 0 となることを検出します。このような場合、
   fget()/fget_light() は失敗します。

#6. Since both fdtable and file structures can be looked up
#   lock-free, they must be installed using rcu_assign_pointer()
#   API. If they are looked up lock-free, rcu_dereference()
#   must be used. However it is advisable to use files_fdtable()
#   and fcheck()/fcheck_files() which take care of these issues.
6. fdtable と file 構造体のいずれもがロックをとらないで参照可能ですから、
  これらについては rcu_assign_pointer() API を用いてインストールする必
  要があります。ロックをとらないで参照する場合、rcu_dereference() を使
  う必要があります。ただし、files_fdtable() と fcheck()/fcheck_files() 

#7. While updating, the fdtable pointer must be looked up while
#   holding files->file_lock. If ->file_lock is dropped, then
#   another thread expand the files thereby creating a new
#   fdtable and making the earlier fdtable pointer stale.
#   For example :
7. 更新時には、fdtable ポインタは files->file_lock を持った状態で参照
  する必要があります。->file_lock を持っていない場合、他のスレッドがそ
  のファイルを拡張して新しい fdtable を作成し、以前の fdtable ポインタ

	fd = locate_fd(files, file, start);
	if (fd >= 0) {
		/* locate_fd() may have expanded fdtable, load the ptr */
		fdt = files_fdtable(files);
		FD_SET(fd, fdt->open_fds);
		FD_CLR(fd, fdt->close_on_exec);

#   Since locate_fd() can drop ->file_lock (and reacquire ->file_lock),
#   the fdtable pointer (fdt) must be loaded after locate_fd().
   locate_fd() が ->file_lock を解放して (その後 ->file_lock を再取
   得する) 可能性があるため、fdtable ポインタ (fdt) は locate_fd() 

Linux カーネル 2.6 付属文書一覧へ戻る