diff options
Diffstat (limited to 'fs/file_table.c')
| -rw-r--r-- | fs/file_table.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index c3e89adf53c..74a9544ac77 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -125,13 +125,13 @@ struct file *get_empty_filp(void) | |||
| 125 | goto fail; | 125 | goto fail; |
| 126 | 126 | ||
| 127 | percpu_counter_inc(&nr_files); | 127 | percpu_counter_inc(&nr_files); |
| 128 | f->f_cred = get_cred(cred); | ||
| 128 | if (security_file_alloc(f)) | 129 | if (security_file_alloc(f)) |
| 129 | goto fail_sec; | 130 | goto fail_sec; |
| 130 | 131 | ||
| 131 | INIT_LIST_HEAD(&f->f_u.fu_list); | 132 | INIT_LIST_HEAD(&f->f_u.fu_list); |
| 132 | atomic_long_set(&f->f_count, 1); | 133 | atomic_long_set(&f->f_count, 1); |
| 133 | rwlock_init(&f->f_owner.lock); | 134 | rwlock_init(&f->f_owner.lock); |
| 134 | f->f_cred = get_cred(cred); | ||
| 135 | spin_lock_init(&f->f_lock); | 135 | spin_lock_init(&f->f_lock); |
| 136 | eventpoll_init_file(f); | 136 | eventpoll_init_file(f); |
| 137 | /* f->f_version: 0 */ | 137 | /* f->f_version: 0 */ |
| @@ -276,11 +276,10 @@ struct file *fget(unsigned int fd) | |||
| 276 | rcu_read_lock(); | 276 | rcu_read_lock(); |
| 277 | file = fcheck_files(files, fd); | 277 | file = fcheck_files(files, fd); |
| 278 | if (file) { | 278 | if (file) { |
| 279 | if (!atomic_long_inc_not_zero(&file->f_count)) { | 279 | /* File object ref couldn't be taken */ |
| 280 | /* File object ref couldn't be taken */ | 280 | if (file->f_mode & FMODE_PATH || |
| 281 | rcu_read_unlock(); | 281 | !atomic_long_inc_not_zero(&file->f_count)) |
| 282 | return NULL; | 282 | file = NULL; |
| 283 | } | ||
| 284 | } | 283 | } |
| 285 | rcu_read_unlock(); | 284 | rcu_read_unlock(); |
| 286 | 285 | ||
| @@ -289,6 +288,25 @@ struct file *fget(unsigned int fd) | |||
| 289 | 288 | ||
| 290 | EXPORT_SYMBOL(fget); | 289 | EXPORT_SYMBOL(fget); |
| 291 | 290 | ||
| 291 | struct file *fget_raw(unsigned int fd) | ||
| 292 | { | ||
| 293 | struct file *file; | ||
| 294 | struct files_struct *files = current->files; | ||
| 295 | |||
| 296 | rcu_read_lock(); | ||
| 297 | file = fcheck_files(files, fd); | ||
| 298 | if (file) { | ||
| 299 | /* File object ref couldn't be taken */ | ||
| 300 | if (!atomic_long_inc_not_zero(&file->f_count)) | ||
| 301 | file = NULL; | ||
| 302 | } | ||
| 303 | rcu_read_unlock(); | ||
| 304 | |||
| 305 | return file; | ||
| 306 | } | ||
| 307 | |||
| 308 | EXPORT_SYMBOL(fget_raw); | ||
| 309 | |||
| 292 | /* | 310 | /* |
| 293 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. | 311 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. |
| 294 | * | 312 | * |
| @@ -313,6 +331,33 @@ struct file *fget_light(unsigned int fd, int *fput_needed) | |||
| 313 | *fput_needed = 0; | 331 | *fput_needed = 0; |
| 314 | if (atomic_read(&files->count) == 1) { | 332 | if (atomic_read(&files->count) == 1) { |
| 315 | file = fcheck_files(files, fd); | 333 | file = fcheck_files(files, fd); |
| 334 | if (file && (file->f_mode & FMODE_PATH)) | ||
| 335 | file = NULL; | ||
| 336 | } else { | ||
| 337 | rcu_read_lock(); | ||
| 338 | file = fcheck_files(files, fd); | ||
| 339 | if (file) { | ||
| 340 | if (!(file->f_mode & FMODE_PATH) && | ||
| 341 | atomic_long_inc_not_zero(&file->f_count)) | ||
| 342 | *fput_needed = 1; | ||
| 343 | else | ||
| 344 | /* Didn't get the reference, someone's freed */ | ||
| 345 | file = NULL; | ||
| 346 | } | ||
| 347 | rcu_read_unlock(); | ||
| 348 | } | ||
| 349 | |||
| 350 | return file; | ||
| 351 | } | ||
| 352 | |||
| 353 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | ||
| 354 | { | ||
| 355 | struct file *file; | ||
| 356 | struct files_struct *files = current->files; | ||
| 357 | |||
| 358 | *fput_needed = 0; | ||
| 359 | if (atomic_read(&files->count) == 1) { | ||
| 360 | file = fcheck_files(files, fd); | ||
| 316 | } else { | 361 | } else { |
| 317 | rcu_read_lock(); | 362 | rcu_read_lock(); |
| 318 | file = fcheck_files(files, fd); | 363 | file = fcheck_files(files, fd); |
