aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-08-15 21:12:10 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-26 21:08:56 -0400
commit0ee8cdfe6af052deb56dccd54838a1eb32fb4ca2 (patch)
tree3671169a822f5ed43482ab4db68d518906385e3d
parentf869e8a7f753e3fd43d6483e796774776f645edb (diff)
take fget() and friends to fs/file.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/file.c106
-rw-r--r--fs/file_table.c106
2 files changed, 106 insertions, 106 deletions
diff --git a/fs/file.c b/fs/file.c
index 0d1bf0515111..6eef55ce30c9 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -625,3 +625,109 @@ void fd_install(unsigned int fd, struct file *file)
625} 625}
626 626
627EXPORT_SYMBOL(fd_install); 627EXPORT_SYMBOL(fd_install);
628
629struct 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
647EXPORT_SYMBOL(fget);
648
649struct 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
666EXPORT_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 */
684struct 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
711struct 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
340EXPORT_SYMBOL(fput); 340EXPORT_SYMBOL(fput);
341 341
342struct 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
360EXPORT_SYMBOL(fget);
361
362struct 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
379EXPORT_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 */
397struct 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
424struct 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
448void put_filp(struct file *file) 342void 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)) {