About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / filesystems / files.txt




Custom Search

Based on kernel version 3.13. Page generated on 2014-01-20 22:02 EST.

1	File management in the Linux kernel
2	-----------------------------------
3	
4	This document describes how locking for files (struct file)
5	and file descriptor table (struct files) works.
6	
7	Up until 2.6.12, the file descriptor table has been protected
8	with a lock (files->file_lock) and reference count (files->count).
9	->file_lock protected accesses to all the file related fields
10	of the table. ->count was used for sharing the file descriptor
11	table between tasks cloned with CLONE_FILES flag. Typically
12	this would be the case for posix threads. As with the common
13	refcounting model in the kernel, the last task doing
14	a put_files_struct() frees the file descriptor (fd) table.
15	The files (struct file) themselves are protected using
16	reference count (->f_count).
17	
18	In the new lock-free model of file descriptor management,
19	the reference counting is similar, but the locking is
20	based on RCU. The file descriptor table contains multiple
21	elements - the fd sets (open_fds and close_on_exec, the
22	array of file pointers, the sizes of the sets and the array
23	etc.). In order for the updates to appear atomic to
24	a lock-free reader, all the elements of the file descriptor
25	table are in a separate structure - struct fdtable.
26	files_struct contains a pointer to struct fdtable through
27	which the actual fd table is accessed. Initially the
28	fdtable is embedded in files_struct itself. On a subsequent
29	expansion of fdtable, a new fdtable structure is allocated
30	and files->fdtab points to the new structure. The fdtable
31	structure is freed with RCU and lock-free readers either
32	see the old fdtable or the new fdtable making the update
33	appear atomic. Here are the locking rules for
34	the fdtable structure -
35	
36	1. All references to the fdtable must be done through
37	   the files_fdtable() macro :
38	
39		struct fdtable *fdt;
40	
41		rcu_read_lock();
42	
43		fdt = files_fdtable(files);
44		....
45		if (n <= fdt->max_fds)
46			....
47		...
48		rcu_read_unlock();
49	
50	   files_fdtable() uses rcu_dereference() macro which takes care of
51	   the memory barrier requirements for lock-free dereference.
52	   The fdtable pointer must be read within the read-side
53	   critical section.
54	
55	2. Reading of the fdtable as described above must be protected
56	   by rcu_read_lock()/rcu_read_unlock().
57	
58	3. For any update to the fd table, files->file_lock must
59	   be held.
60	
61	4. To look up the file structure given an fd, a reader
62	   must use either fcheck() or fcheck_files() APIs. These
63	   take care of barrier requirements due to lock-free lookup.
64	   An example :
65	
66		struct file *file;
67	
68		rcu_read_lock();
69		file = fcheck(fd);
70		if (file) {
71			...
72		}
73		....
74		rcu_read_unlock();
75	
76	5. Handling of the file structures is special. Since the look-up
77	   of the fd (fget()/fget_light()) are lock-free, it is possible
78	   that look-up may race with the last put() operation on the
79	   file structure. This is avoided using atomic_long_inc_not_zero()
80	   on ->f_count :
81	
82		rcu_read_lock();
83		file = fcheck_files(files, fd);
84		if (file) {
85			if (atomic_long_inc_not_zero(&file->f_count))
86				*fput_needed = 1;
87			else
88			/* Didn't get the reference, someone's freed */
89				file = NULL;
90		}
91		rcu_read_unlock();
92		....
93		return file;
94	
95	   atomic_long_inc_not_zero() detects if refcounts is already zero or
96	   goes to zero during increment. If it does, we fail
97	   fget()/fget_light().
98	
99	6. Since both fdtable and file structures can be looked up
100	   lock-free, they must be installed using rcu_assign_pointer()
101	   API. If they are looked up lock-free, rcu_dereference()
102	   must be used. However it is advisable to use files_fdtable()
103	   and fcheck()/fcheck_files() which take care of these issues.
104	
105	7. While updating, the fdtable pointer must be looked up while
106	   holding files->file_lock. If ->file_lock is dropped, then
107	   another thread expand the files thereby creating a new
108	   fdtable and making the earlier fdtable pointer stale.
109	   For example :
110	
111		spin_lock(&files->file_lock);
112		fd = locate_fd(files, file, start);
113		if (fd >= 0) {
114			/* locate_fd() may have expanded fdtable, load the ptr */
115			fdt = files_fdtable(files);
116			__set_open_fd(fd, fdt);
117			__clear_close_on_exec(fd, fdt);
118			spin_unlock(&files->file_lock);
119		.....
120	
121	   Since locate_fd() can drop ->file_lock (and reacquire ->file_lock),
122	   the fdtable pointer (fdt) must be loaded after locate_fd().
Hide Line Numbers
About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Information is copyright its respective author. All material is available from the Linux Kernel Source distributed under a GPL License. This page is provided as a free service by mjmwired.net.