diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-15 21:12:10 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:08:56 -0400 |
commit | 0ee8cdfe6af052deb56dccd54838a1eb32fb4ca2 (patch) | |
tree | 3671169a822f5ed43482ab4db68d518906385e3d | |
parent | f869e8a7f753e3fd43d6483e796774776f645edb (diff) |
take fget() and friends to fs/file.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/file.c | 106 | ||||
-rw-r--r-- | fs/file_table.c | 106 |
2 files changed, 106 insertions, 106 deletions
@@ -625,3 +625,109 @@ void fd_install(unsigned int fd, struct file *file) | |||
625 | } | 625 | } |
626 | 626 | ||
627 | EXPORT_SYMBOL(fd_install); | 627 | EXPORT_SYMBOL(fd_install); |
628 | |||
629 | struct file *fget(unsigned int fd) | ||
630 | { | ||
631 | struct file *file; | ||
632 | struct files_struct *files = current->files; | ||
633 | |||
634 | rcu_read_lock(); | ||
635 | file = fcheck_files(files, fd); | ||
636 | if (file) { | ||
637 | /* File object ref couldn't be taken */ | ||
638 | if (file->f_mode & FMODE_PATH || | ||
639 | !atomic_long_inc_not_zero(&file->f_count)) | ||
640 | file = NULL; | ||
641 | } | ||
642 | rcu_read_unlock(); | ||
643 | |||
644 | return file; | ||
645 | } | ||
646 | |||
647 | EXPORT_SYMBOL(fget); | ||
648 | |||
649 | struct file *fget_raw(unsigned int fd) | ||
650 | { | ||
651 | struct file *file; | ||
652 | struct files_struct *files = current->files; | ||
653 | |||
654 | rcu_read_lock(); | ||
655 | file = fcheck_files(files, fd); | ||
656 | if (file) { | ||
657 | /* File object ref couldn't be taken */ | ||
658 | if (!atomic_long_inc_not_zero(&file->f_count)) | ||
659 | file = NULL; | ||
660 | } | ||
661 | rcu_read_unlock(); | ||
662 | |||
663 | return file; | ||
664 | } | ||
665 | |||
666 | EXPORT_SYMBOL(fget_raw); | ||
667 | |||
668 | /* | ||
669 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. | ||
670 | * | ||
671 | * You can use this instead of fget if you satisfy all of the following | ||
672 | * conditions: | ||
673 | * 1) You must call fput_light before exiting the syscall and returning control | ||
674 | * to userspace (i.e. you cannot remember the returned struct file * after | ||
675 | * returning to userspace). | ||
676 | * 2) You must not call filp_close on the returned struct file * in between | ||
677 | * calls to fget_light and fput_light. | ||
678 | * 3) You must not clone the current task in between the calls to fget_light | ||
679 | * and fput_light. | ||
680 | * | ||
681 | * The fput_needed flag returned by fget_light should be passed to the | ||
682 | * corresponding fput_light. | ||
683 | */ | ||
684 | struct file *fget_light(unsigned int fd, int *fput_needed) | ||
685 | { | ||
686 | struct file *file; | ||
687 | struct files_struct *files = current->files; | ||
688 | |||
689 | *fput_needed = 0; | ||
690 | if (atomic_read(&files->count) == 1) { | ||
691 | file = fcheck_files(files, fd); | ||
692 | if (file && (file->f_mode & FMODE_PATH)) | ||
693 | file = NULL; | ||
694 | } else { | ||
695 | rcu_read_lock(); | ||
696 | file = fcheck_files(files, fd); | ||
697 | if (file) { | ||
698 | if (!(file->f_mode & FMODE_PATH) && | ||
699 | atomic_long_inc_not_zero(&file->f_count)) | ||
700 | *fput_needed = 1; | ||
701 | else | ||
702 | /* Didn't get the reference, someone's freed */ | ||
703 | file = NULL; | ||
704 | } | ||
705 | rcu_read_unlock(); | ||
706 | } | ||
707 | |||
708 | return file; | ||
709 | } | ||
710 | |||
711 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | ||
712 | { | ||
713 | struct file *file; | ||
714 | struct files_struct *files = current->files; | ||
715 | |||
716 | *fput_needed = 0; | ||
717 | if (atomic_read(&files->count) == 1) { | ||
718 | file = fcheck_files(files, fd); | ||
719 | } else { | ||
720 | rcu_read_lock(); | ||
721 | file = fcheck_files(files, fd); | ||
722 | if (file) { | ||
723 | if (atomic_long_inc_not_zero(&file->f_count)) | ||
724 | *fput_needed = 1; | ||
725 | else | ||
726 | /* Didn't get the reference, someone's freed */ | ||
727 | file = NULL; | ||
728 | } | ||
729 | rcu_read_unlock(); | ||
730 | } | ||
731 | |||
732 | return file; | ||
733 | } | ||
diff --git a/fs/file_table.c b/fs/file_table.c index 701985e4ccda..c6780163bf3e 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -339,112 +339,6 @@ void __fput_sync(struct file *file) | |||
339 | 339 | ||
340 | EXPORT_SYMBOL(fput); | 340 | EXPORT_SYMBOL(fput); |
341 | 341 | ||
342 | struct file *fget(unsigned int fd) | ||
343 | { | ||
344 | struct file *file; | ||
345 | struct files_struct *files = current->files; | ||
346 | |||
347 | rcu_read_lock(); | ||
348 | file = fcheck_files(files, fd); | ||
349 | if (file) { | ||
350 | /* File object ref couldn't be taken */ | ||
351 | if (file->f_mode & FMODE_PATH || | ||
352 | !atomic_long_inc_not_zero(&file->f_count)) | ||
353 | file = NULL; | ||
354 | } | ||
355 | rcu_read_unlock(); | ||
356 | |||
357 | return file; | ||
358 | } | ||
359 | |||
360 | EXPORT_SYMBOL(fget); | ||
361 | |||
362 | struct file *fget_raw(unsigned int fd) | ||
363 | { | ||
364 | struct file *file; | ||
365 | struct files_struct *files = current->files; | ||
366 | |||
367 | rcu_read_lock(); | ||
368 | file = fcheck_files(files, fd); | ||
369 | if (file) { | ||
370 | /* File object ref couldn't be taken */ | ||
371 | if (!atomic_long_inc_not_zero(&file->f_count)) | ||
372 | file = NULL; | ||
373 | } | ||
374 | rcu_read_unlock(); | ||
375 | |||
376 | return file; | ||
377 | } | ||
378 | |||
379 | EXPORT_SYMBOL(fget_raw); | ||
380 | |||
381 | /* | ||
382 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. | ||
383 | * | ||
384 | * You can use this instead of fget if you satisfy all of the following | ||
385 | * conditions: | ||
386 | * 1) You must call fput_light before exiting the syscall and returning control | ||
387 | * to userspace (i.e. you cannot remember the returned struct file * after | ||
388 | * returning to userspace). | ||
389 | * 2) You must not call filp_close on the returned struct file * in between | ||
390 | * calls to fget_light and fput_light. | ||
391 | * 3) You must not clone the current task in between the calls to fget_light | ||
392 | * and fput_light. | ||
393 | * | ||
394 | * The fput_needed flag returned by fget_light should be passed to the | ||
395 | * corresponding fput_light. | ||
396 | */ | ||
397 | struct file *fget_light(unsigned int fd, int *fput_needed) | ||
398 | { | ||
399 | struct file *file; | ||
400 | struct files_struct *files = current->files; | ||
401 | |||
402 | *fput_needed = 0; | ||
403 | if (atomic_read(&files->count) == 1) { | ||
404 | file = fcheck_files(files, fd); | ||
405 | if (file && (file->f_mode & FMODE_PATH)) | ||
406 | file = NULL; | ||
407 | } else { | ||
408 | rcu_read_lock(); | ||
409 | file = fcheck_files(files, fd); | ||
410 | if (file) { | ||
411 | if (!(file->f_mode & FMODE_PATH) && | ||
412 | atomic_long_inc_not_zero(&file->f_count)) | ||
413 | *fput_needed = 1; | ||
414 | else | ||
415 | /* Didn't get the reference, someone's freed */ | ||
416 | file = NULL; | ||
417 | } | ||
418 | rcu_read_unlock(); | ||
419 | } | ||
420 | |||
421 | return file; | ||
422 | } | ||
423 | |||
424 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | ||
425 | { | ||
426 | struct file *file; | ||
427 | struct files_struct *files = current->files; | ||
428 | |||
429 | *fput_needed = 0; | ||
430 | if (atomic_read(&files->count) == 1) { | ||
431 | file = fcheck_files(files, fd); | ||
432 | } else { | ||
433 | rcu_read_lock(); | ||
434 | file = fcheck_files(files, fd); | ||
435 | if (file) { | ||
436 | if (atomic_long_inc_not_zero(&file->f_count)) | ||
437 | *fput_needed = 1; | ||
438 | else | ||
439 | /* Didn't get the reference, someone's freed */ | ||
440 | file = NULL; | ||
441 | } | ||
442 | rcu_read_unlock(); | ||
443 | } | ||
444 | |||
445 | return file; | ||
446 | } | ||
447 | |||
448 | void put_filp(struct file *file) | 342 | void put_filp(struct file *file) |
449 | { | 343 | { |
450 | if (atomic_long_dec_and_test(&file->f_count)) { | 344 | if (atomic_long_dec_and_test(&file->f_count)) { |