Blame view

fs/file_table.c 6.71 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   *  linux/fs/file_table.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *  Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   */
  
  #include <linux/string.h>
  #include <linux/slab.h>
  #include <linux/file.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/smp_lock.h>
  #include <linux/fs.h>
  #include <linux/security.h>
  #include <linux/eventpoll.h>
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
17
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/mount.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
19
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <linux/cdev.h>
0eeca2830   Robert Love   [PATCH] inotify
21
  #include <linux/fsnotify.h>
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
22
23
24
25
  #include <linux/sysctl.h>
  #include <linux/percpu_counter.h>
  
  #include <asm/atomic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
  
  /* sysctl tunables... */
  struct files_stat_struct files_stat = {
  	.max_files = NR_FILE
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  /* public. Not pretty! */
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
32
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

529bf6be5   Dipankar Sarma   [PATCH] fix file ...
34
  static struct percpu_counter nr_files __cacheline_aligned_in_smp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

529bf6be5   Dipankar Sarma   [PATCH] fix file ...
36
  static inline void file_free_rcu(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  {
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
38
39
  	struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
  	kmem_cache_free(filp_cachep, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  }
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
41
  static inline void file_free(struct file *f)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
43
44
  	percpu_counter_dec(&nr_files);
  	call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  }
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
46
47
48
49
  /*
   * Return the total number of open files in the system
   */
  static int get_nr_files(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  {
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
51
  	return percpu_counter_read_positive(&nr_files);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  }
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
53
54
55
56
  /*
   * Return the maximum number of open files in the system
   */
  int get_max_files(void)
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
57
  {
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
58
  	return files_stat.max_files;
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
59
  }
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  EXPORT_SYMBOL_GPL(get_max_files);
  
  /*
   * Handle nr_files sysctl
   */
  #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
  int proc_nr_files(ctl_table *table, int write, struct file *filp,
                       void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	files_stat.nr_files = get_nr_files();
  	return proc_dointvec(table, write, filp, buffer, lenp, ppos);
  }
  #else
  int proc_nr_files(ctl_table *table, int write, struct file *filp,
                       void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	return -ENOSYS;
  }
  #endif
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
79

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
  /* Find an unused file structure and return a pointer to it.
   * Returns NULL, if there are no more free file structures or
   * we run out of memory.
   */
  struct file *get_empty_filp(void)
  {
5a6b7951b   Benjamin LaHaise   [PATCH] get_empty...
86
  	struct task_struct *tsk;
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
87
  	static int old_max;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
  	struct file * f;
  
  	/*
  	 * Privileged users can go above max_files
  	 */
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
93
94
95
96
97
98
99
100
  	if (get_nr_files() >= files_stat.max_files && !capable(CAP_SYS_ADMIN)) {
  		/*
  		 * percpu_counters are inaccurate.  Do an expensive check before
  		 * we go and fail.
  		 */
  		if (percpu_counter_sum(&nr_files) >= files_stat.max_files)
  			goto over;
  	}
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
101
102
103
104
  
  	f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
  	if (f == NULL)
  		goto fail;
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
105
  	percpu_counter_inc(&nr_files);
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
106
107
108
  	memset(f, 0, sizeof(*f));
  	if (security_file_alloc(f))
  		goto fail_sec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

5a6b7951b   Benjamin LaHaise   [PATCH] get_empty...
110
111
  	tsk = current;
  	INIT_LIST_HEAD(&f->f_u.fu_list);
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
112
  	atomic_set(&f->f_count, 1);
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
113
  	rwlock_init(&f->f_owner.lock);
5a6b7951b   Benjamin LaHaise   [PATCH] get_empty...
114
115
116
  	f->f_uid = tsk->fsuid;
  	f->f_gid = tsk->fsgid;
  	eventpoll_init_file(f);
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
117
  	/* f->f_version: 0 */
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
118
119
120
  	return f;
  
  over:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	/* Ran out of filps - report that */
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
122
  	if (get_nr_files() > old_max) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
  		printk(KERN_INFO "VFS: file-max limit %d reached
  ",
529bf6be5   Dipankar Sarma   [PATCH] fix file ...
125
126
  					get_max_files());
  		old_max = get_nr_files();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	}
af4d2ecbf   Kirill Korotaev   [PATCH] Fix of bo...
128
129
130
131
  	goto fail;
  
  fail_sec:
  	file_free(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
  fail:
  	return NULL;
  }
  
  EXPORT_SYMBOL(get_empty_filp);
  
  void fastcall fput(struct file *file)
  {
095975da2   Nick Piggin   [PATCH] rcu file:...
140
  	if (atomic_dec_and_test(&file->f_count))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  		__fput(file);
  }
  
  EXPORT_SYMBOL(fput);
  
  /* __fput is called from task context when aio completion releases the last
   * last use of a struct file *.  Do not use otherwise.
   */
  void fastcall __fput(struct file *file)
  {
  	struct dentry *dentry = file->f_dentry;
  	struct vfsmount *mnt = file->f_vfsmnt;
  	struct inode *inode = dentry->d_inode;
  
  	might_sleep();
0eeca2830   Robert Love   [PATCH] inotify
156
157
  
  	fsnotify_close(file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  	/*
  	 * The function eventpoll_release() should be the first called
  	 * in the file cleanup chain.
  	 */
  	eventpoll_release(file);
  	locks_remove_flock(file);
  
  	if (file->f_op && file->f_op->release)
  		file->f_op->release(inode, file);
  	security_file_free(file);
  	if (unlikely(inode->i_cdev != NULL))
  		cdev_put(inode->i_cdev);
  	fops_put(file->f_op);
  	if (file->f_mode & FMODE_WRITE)
  		put_write_access(inode);
  	file_kill(file);
  	file->f_dentry = NULL;
  	file->f_vfsmnt = NULL;
  	file_free(file);
  	dput(dentry);
  	mntput(mnt);
  }
  
  struct file fastcall *fget(unsigned int fd)
  {
  	struct file *file;
  	struct files_struct *files = current->files;
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
185
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	file = fcheck_files(files, fd);
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
187
  	if (file) {
095975da2   Nick Piggin   [PATCH] rcu file:...
188
  		if (!atomic_inc_not_zero(&file->f_count)) {
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
189
190
191
192
193
194
  			/* File object ref couldn't be taken */
  			rcu_read_unlock();
  			return NULL;
  		}
  	}
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  	return file;
  }
  
  EXPORT_SYMBOL(fget);
  
  /*
   * Lightweight file lookup - no refcnt increment if fd table isn't shared. 
   * You can use this only if it is guranteed that the current task already 
   * holds a refcnt to that file. That check has to be done at fget() only
   * and a flag is returned to be passed to the corresponding fput_light().
   * There must not be a cloning between an fget_light/fput_light pair.
   */
  struct file fastcall *fget_light(unsigned int fd, int *fput_needed)
  {
  	struct file *file;
  	struct files_struct *files = current->files;
  
  	*fput_needed = 0;
  	if (likely((atomic_read(&files->count) == 1))) {
  		file = fcheck_files(files, fd);
  	} else {
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
216
  		rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
  		file = fcheck_files(files, fd);
  		if (file) {
095975da2   Nick Piggin   [PATCH] rcu file:...
219
  			if (atomic_inc_not_zero(&file->f_count))
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
220
221
222
223
  				*fput_needed = 1;
  			else
  				/* Didn't get the reference, someone's freed */
  				file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  		}
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
225
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  	}
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
233
  	return file;
  }
  
  
  void put_filp(struct file *file)
  {
095975da2   Nick Piggin   [PATCH] rcu file:...
234
  	if (atomic_dec_and_test(&file->f_count)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
238
239
240
241
242
243
244
245
  		security_file_free(file);
  		file_kill(file);
  		file_free(file);
  	}
  }
  
  void file_move(struct file *file, struct list_head *list)
  {
  	if (!list)
  		return;
  	file_list_lock();
2f5120166   Eric Dumazet   [PATCH] reduce si...
246
  	list_move(&file->f_u.fu_list, list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
  	file_list_unlock();
  }
  
  void file_kill(struct file *file)
  {
2f5120166   Eric Dumazet   [PATCH] reduce si...
252
  	if (!list_empty(&file->f_u.fu_list)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  		file_list_lock();
2f5120166   Eric Dumazet   [PATCH] reduce si...
254
  		list_del_init(&file->f_u.fu_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
260
261
262
263
264
265
  		file_list_unlock();
  	}
  }
  
  int fs_may_remount_ro(struct super_block *sb)
  {
  	struct list_head *p;
  
  	/* Check that no files are currently opened for writing. */
  	file_list_lock();
  	list_for_each(p, &sb->s_files) {
2f5120166   Eric Dumazet   [PATCH] reduce si...
266
  		struct file *file = list_entry(p, struct file, f_u.fu_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  		struct inode *inode = file->f_dentry->d_inode;
  
  		/* File with pending delete? */
  		if (inode->i_nlink == 0)
  			goto too_bad;
  
  		/* Writeable file? */
  		if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
  			goto too_bad;
  	}
  	file_list_unlock();
  	return 1; /* Tis' cool bro. */
  too_bad:
  	file_list_unlock();
  	return 0;
  }
  
  void __init files_init(unsigned long mempages)
  { 
  	int n; 
  	/* One file with associated inode and dcache is very roughly 1K. 
  	 * Per default don't use more than 10% of our memory for files. 
  	 */ 
  
  	n = (mempages * (PAGE_SIZE / 1024)) / 10;
  	files_stat.max_files = n; 
  	if (files_stat.max_files < NR_FILE)
  		files_stat.max_files = NR_FILE;
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
295
  	files_defer_init();
0216bfcff   Mingming Cao   [PATCH] percpu co...
296
  	percpu_counter_init(&nr_files, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  }