aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file_table.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-08-31 03:45:21 -0400
committerIngo Molnar <mingo@elte.hu>2010-08-31 03:45:46 -0400
commitdaab7fc734a53fdeaf844b7c03053118ad1769da (patch)
tree575deb3cdcc6dda562acaed6f7c29bc81ae01cf2 /fs/file_table.c
parent774ea0bcb27f57b6fd521b3b6c43237782fed4b9 (diff)
parent2bfc96a127bc1cc94d26bfaa40159966064f9c8c (diff)
Merge commit 'v2.6.36-rc3' into x86/memblock
Conflicts: arch/x86/kernel/trampoline.c mm/memblock.c Merge reason: Resolve the conflicts, update to latest upstream. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/file_table.c')
-rw-r--r--fs/file_table.c143
1 files changed, 109 insertions, 34 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index 5c7d10ead4ad..a04bdd81c11c 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -20,7 +20,9 @@
20#include <linux/cdev.h> 20#include <linux/cdev.h>
21#include <linux/fsnotify.h> 21#include <linux/fsnotify.h>
22#include <linux/sysctl.h> 22#include <linux/sysctl.h>
23#include <linux/lglock.h>
23#include <linux/percpu_counter.h> 24#include <linux/percpu_counter.h>
25#include <linux/percpu.h>
24#include <linux/ima.h> 26#include <linux/ima.h>
25 27
26#include <asm/atomic.h> 28#include <asm/atomic.h>
@@ -32,8 +34,8 @@ struct files_stat_struct files_stat = {
32 .max_files = NR_FILE 34 .max_files = NR_FILE
33}; 35};
34 36
35/* public. Not pretty! */ 37DECLARE_LGLOCK(files_lglock);
36__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); 38DEFINE_LGLOCK(files_lglock);
37 39
38/* SLAB cache for file structures */ 40/* SLAB cache for file structures */
39static struct kmem_cache *filp_cachep __read_mostly; 41static struct kmem_cache *filp_cachep __read_mostly;
@@ -249,7 +251,7 @@ static void __fput(struct file *file)
249 cdev_put(inode->i_cdev); 251 cdev_put(inode->i_cdev);
250 fops_put(file->f_op); 252 fops_put(file->f_op);
251 put_pid(file->f_owner.pid); 253 put_pid(file->f_owner.pid);
252 file_kill(file); 254 file_sb_list_del(file);
253 if (file->f_mode & FMODE_WRITE) 255 if (file->f_mode & FMODE_WRITE)
254 drop_file_write_access(file); 256 drop_file_write_access(file);
255 file->f_path.dentry = NULL; 257 file->f_path.dentry = NULL;
@@ -289,11 +291,20 @@ struct file *fget(unsigned int fd)
289EXPORT_SYMBOL(fget); 291EXPORT_SYMBOL(fget);
290 292
291/* 293/*
292 * Lightweight file lookup - no refcnt increment if fd table isn't shared. 294 * Lightweight file lookup - no refcnt increment if fd table isn't shared.
293 * You can use this only if it is guranteed that the current task already 295 *
294 * holds a refcnt to that file. That check has to be done at fget() only 296 * You can use this instead of fget if you satisfy all of the following
295 * and a flag is returned to be passed to the corresponding fput_light(). 297 * conditions:
296 * There must not be a cloning between an fget_light/fput_light pair. 298 * 1) You must call fput_light before exiting the syscall and returning control
299 * to userspace (i.e. you cannot remember the returned struct file * after
300 * returning to userspace).
301 * 2) You must not call filp_close on the returned struct file * in between
302 * calls to fget_light and fput_light.
303 * 3) You must not clone the current task in between the calls to fget_light
304 * and fput_light.
305 *
306 * The fput_needed flag returned by fget_light should be passed to the
307 * corresponding fput_light.
297 */ 308 */
298struct file *fget_light(unsigned int fd, int *fput_needed) 309struct file *fget_light(unsigned int fd, int *fput_needed)
299{ 310{
@@ -319,41 +330,107 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
319 return file; 330 return file;
320} 331}
321 332
322
323void put_filp(struct file *file) 333void put_filp(struct file *file)
324{ 334{
325 if (atomic_long_dec_and_test(&file->f_count)) { 335 if (atomic_long_dec_and_test(&file->f_count)) {
326 security_file_free(file); 336 security_file_free(file);
327 file_kill(file); 337 file_sb_list_del(file);
328 file_free(file); 338 file_free(file);
329 } 339 }
330} 340}
331 341
332void file_move(struct file *file, struct list_head *list) 342static inline int file_list_cpu(struct file *file)
333{ 343{
334 if (!list) 344#ifdef CONFIG_SMP
335 return; 345 return file->f_sb_list_cpu;
336 file_list_lock(); 346#else
337 list_move(&file->f_u.fu_list, list); 347 return smp_processor_id();
338 file_list_unlock(); 348#endif
339} 349}
340 350
341void file_kill(struct file *file) 351/* helper for file_sb_list_add to reduce ifdefs */
352static inline void __file_sb_list_add(struct file *file, struct super_block *sb)
353{
354 struct list_head *list;
355#ifdef CONFIG_SMP
356 int cpu;
357 cpu = smp_processor_id();
358 file->f_sb_list_cpu = cpu;
359 list = per_cpu_ptr(sb->s_files, cpu);
360#else
361 list = &sb->s_files;
362#endif
363 list_add(&file->f_u.fu_list, list);
364}
365
366/**
367 * file_sb_list_add - add a file to the sb's file list
368 * @file: file to add
369 * @sb: sb to add it to
370 *
371 * Use this function to associate a file with the superblock of the inode it
372 * refers to.
373 */
374void file_sb_list_add(struct file *file, struct super_block *sb)
375{
376 lg_local_lock(files_lglock);
377 __file_sb_list_add(file, sb);
378 lg_local_unlock(files_lglock);
379}
380
381/**
382 * file_sb_list_del - remove a file from the sb's file list
383 * @file: file to remove
384 * @sb: sb to remove it from
385 *
386 * Use this function to remove a file from its superblock.
387 */
388void file_sb_list_del(struct file *file)
342{ 389{
343 if (!list_empty(&file->f_u.fu_list)) { 390 if (!list_empty(&file->f_u.fu_list)) {
344 file_list_lock(); 391 lg_local_lock_cpu(files_lglock, file_list_cpu(file));
345 list_del_init(&file->f_u.fu_list); 392 list_del_init(&file->f_u.fu_list);
346 file_list_unlock(); 393 lg_local_unlock_cpu(files_lglock, file_list_cpu(file));
347 } 394 }
348} 395}
349 396
397#ifdef CONFIG_SMP
398
399/*
400 * These macros iterate all files on all CPUs for a given superblock.
401 * files_lglock must be held globally.
402 */
403#define do_file_list_for_each_entry(__sb, __file) \
404{ \
405 int i; \
406 for_each_possible_cpu(i) { \
407 struct list_head *list; \
408 list = per_cpu_ptr((__sb)->s_files, i); \
409 list_for_each_entry((__file), list, f_u.fu_list)
410
411#define while_file_list_for_each_entry \
412 } \
413}
414
415#else
416
417#define do_file_list_for_each_entry(__sb, __file) \
418{ \
419 struct list_head *list; \
420 list = &(sb)->s_files; \
421 list_for_each_entry((__file), list, f_u.fu_list)
422
423#define while_file_list_for_each_entry \
424}
425
426#endif
427
350int fs_may_remount_ro(struct super_block *sb) 428int fs_may_remount_ro(struct super_block *sb)
351{ 429{
352 struct file *file; 430 struct file *file;
353
354 /* Check that no files are currently opened for writing. */ 431 /* Check that no files are currently opened for writing. */
355 file_list_lock(); 432 lg_global_lock(files_lglock);
356 list_for_each_entry(file, &sb->s_files, f_u.fu_list) { 433 do_file_list_for_each_entry(sb, file) {
357 struct inode *inode = file->f_path.dentry->d_inode; 434 struct inode *inode = file->f_path.dentry->d_inode;
358 435
359 /* File with pending delete? */ 436 /* File with pending delete? */
@@ -363,11 +440,11 @@ int fs_may_remount_ro(struct super_block *sb)
363 /* Writeable file? */ 440 /* Writeable file? */
364 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) 441 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
365 goto too_bad; 442 goto too_bad;
366 } 443 } while_file_list_for_each_entry;
367 file_list_unlock(); 444 lg_global_unlock(files_lglock);
368 return 1; /* Tis' cool bro. */ 445 return 1; /* Tis' cool bro. */
369too_bad: 446too_bad:
370 file_list_unlock(); 447 lg_global_unlock(files_lglock);
371 return 0; 448 return 0;
372} 449}
373 450
@@ -383,8 +460,8 @@ void mark_files_ro(struct super_block *sb)
383 struct file *f; 460 struct file *f;
384 461
385retry: 462retry:
386 file_list_lock(); 463 lg_global_lock(files_lglock);
387 list_for_each_entry(f, &sb->s_files, f_u.fu_list) { 464 do_file_list_for_each_entry(sb, f) {
388 struct vfsmount *mnt; 465 struct vfsmount *mnt;
389 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) 466 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
390 continue; 467 continue;
@@ -399,16 +476,13 @@ retry:
399 continue; 476 continue;
400 file_release_write(f); 477 file_release_write(f);
401 mnt = mntget(f->f_path.mnt); 478 mnt = mntget(f->f_path.mnt);
402 file_list_unlock(); 479 /* This can sleep, so we can't hold the spinlock. */
403 /* 480 lg_global_unlock(files_lglock);
404 * This can sleep, so we can't hold
405 * the file_list_lock() spinlock.
406 */
407 mnt_drop_write(mnt); 481 mnt_drop_write(mnt);
408 mntput(mnt); 482 mntput(mnt);
409 goto retry; 483 goto retry;
410 } 484 } while_file_list_for_each_entry;
411 file_list_unlock(); 485 lg_global_unlock(files_lglock);
412} 486}
413 487
414void __init files_init(unsigned long mempages) 488void __init files_init(unsigned long mempages)
@@ -428,5 +502,6 @@ void __init files_init(unsigned long mempages)
428 if (files_stat.max_files < NR_FILE) 502 if (files_stat.max_files < NR_FILE)
429 files_stat.max_files = NR_FILE; 503 files_stat.max_files = NR_FILE;
430 files_defer_init(); 504 files_defer_init();
505 lg_lock_init(files_lglock);
431 percpu_counter_init(&nr_files, 0); 506 percpu_counter_init(&nr_files, 0);
432} 507}