diff options
| author | 2011-03-18 10:38:53 +0100 | |
|---|---|---|
| committer | 2011-03-18 10:39:00 +0100 | |
| commit | 8dd8997d2c56c9f248294805e129e1fc69444380 (patch) | |
| tree | 3b030a04295fc031db98746c4074c2df1ed6a19f /fs/file_table.c | |
| parent | x86: Use PentiumPro-optimized partial_csum() on VIA C7 (diff) | |
| parent | Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip (diff) | |
| download | wireguard-linux-8dd8997d2c56c9f248294805e129e1fc69444380.tar.xz wireguard-linux-8dd8997d2c56c9f248294805e129e1fc69444380.zip | |
Merge branch 'linus' into x86/urgent
Merge reason: Merge upstream commits to avoid conflicts in upcoming patches.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to '')
| -rw-r--r-- | fs/file_table.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index eb36b6b17e26..74a9544ac770 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -276,11 +276,10 @@ struct file *fget(unsigned int fd) rcu_read_lock(); file = fcheck_files(files, fd); if (file) { - if (!atomic_long_inc_not_zero(&file->f_count)) { - /* File object ref couldn't be taken */ - rcu_read_unlock(); - return NULL; - } + /* File object ref couldn't be taken */ + if (file->f_mode & FMODE_PATH || + !atomic_long_inc_not_zero(&file->f_count)) + file = NULL; } rcu_read_unlock(); @@ -289,6 +288,25 @@ struct file *fget(unsigned int fd) EXPORT_SYMBOL(fget); +struct file *fget_raw(unsigned int fd) +{ + struct file *file; + struct files_struct *files = current->files; + + rcu_read_lock(); + file = fcheck_files(files, fd); + if (file) { + /* File object ref couldn't be taken */ + if (!atomic_long_inc_not_zero(&file->f_count)) + file = NULL; + } + rcu_read_unlock(); + + return file; +} + +EXPORT_SYMBOL(fget_raw); + /* * Lightweight file lookup - no refcnt increment if fd table isn't shared. * @@ -313,6 +331,33 @@ struct file *fget_light(unsigned int fd, int *fput_needed) *fput_needed = 0; if (atomic_read(&files->count) == 1) { file = fcheck_files(files, fd); + if (file && (file->f_mode & FMODE_PATH)) + file = NULL; + } else { + rcu_read_lock(); + file = fcheck_files(files, fd); + if (file) { + if (!(file->f_mode & FMODE_PATH) && + atomic_long_inc_not_zero(&file->f_count)) + *fput_needed = 1; + else + /* Didn't get the reference, someone's freed */ + file = NULL; + } + rcu_read_unlock(); + } + + return file; +} + +struct file *fget_raw_light(unsigned int fd, int *fput_needed) +{ + struct file *file; + struct files_struct *files = current->files; + + *fput_needed = 0; + if (atomic_read(&files->count) == 1) { + file = fcheck_files(files, fd); } else { rcu_read_lock(); file = fcheck_files(files, fd); |
