diff options
Diffstat (limited to 'fs/file.c')
| -rw-r--r-- | fs/file.c | 47 |
1 files changed, 33 insertions, 14 deletions
| @@ -497,7 +497,7 @@ repeat: | |||
| 497 | error = fd; | 497 | error = fd; |
| 498 | #if 1 | 498 | #if 1 |
| 499 | /* Sanity check */ | 499 | /* Sanity check */ |
| 500 | if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { | 500 | if (rcu_access_pointer(fdt->fd[fd]) != NULL) { |
| 501 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); | 501 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); |
| 502 | rcu_assign_pointer(fdt->fd[fd], NULL); | 502 | rcu_assign_pointer(fdt->fd[fd], NULL); |
| 503 | } | 503 | } |
| @@ -683,35 +683,54 @@ EXPORT_SYMBOL(fget_raw); | |||
| 683 | * The fput_needed flag returned by fget_light should be passed to the | 683 | * The fput_needed flag returned by fget_light should be passed to the |
| 684 | * corresponding fput_light. | 684 | * corresponding fput_light. |
| 685 | */ | 685 | */ |
| 686 | struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) | 686 | static unsigned long __fget_light(unsigned int fd, fmode_t mask) |
| 687 | { | 687 | { |
| 688 | struct files_struct *files = current->files; | 688 | struct files_struct *files = current->files; |
| 689 | struct file *file; | 689 | struct file *file; |
| 690 | 690 | ||
| 691 | *fput_needed = 0; | ||
| 692 | if (atomic_read(&files->count) == 1) { | 691 | if (atomic_read(&files->count) == 1) { |
| 693 | file = __fcheck_files(files, fd); | 692 | file = __fcheck_files(files, fd); |
| 694 | if (file && (file->f_mode & mask)) | 693 | if (!file || unlikely(file->f_mode & mask)) |
| 695 | file = NULL; | 694 | return 0; |
| 695 | return (unsigned long)file; | ||
| 696 | } else { | 696 | } else { |
| 697 | file = __fget(fd, mask); | 697 | file = __fget(fd, mask); |
| 698 | if (file) | 698 | if (!file) |
| 699 | *fput_needed = 1; | 699 | return 0; |
| 700 | return FDPUT_FPUT | (unsigned long)file; | ||
| 700 | } | 701 | } |
| 701 | |||
| 702 | return file; | ||
| 703 | } | 702 | } |
| 704 | struct file *fget_light(unsigned int fd, int *fput_needed) | 703 | unsigned long __fdget(unsigned int fd) |
| 705 | { | 704 | { |
| 706 | return __fget_light(fd, FMODE_PATH, fput_needed); | 705 | return __fget_light(fd, FMODE_PATH); |
| 707 | } | 706 | } |
| 708 | EXPORT_SYMBOL(fget_light); | 707 | EXPORT_SYMBOL(__fdget); |
| 709 | 708 | ||
| 710 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | 709 | unsigned long __fdget_raw(unsigned int fd) |
| 711 | { | 710 | { |
| 712 | return __fget_light(fd, 0, fput_needed); | 711 | return __fget_light(fd, 0); |
| 713 | } | 712 | } |
| 714 | 713 | ||
| 714 | unsigned long __fdget_pos(unsigned int fd) | ||
| 715 | { | ||
| 716 | unsigned long v = __fdget(fd); | ||
| 717 | struct file *file = (struct file *)(v & ~3); | ||
| 718 | |||
| 719 | if (file && (file->f_mode & FMODE_ATOMIC_POS)) { | ||
| 720 | if (file_count(file) > 1) { | ||
| 721 | v |= FDPUT_POS_UNLOCK; | ||
| 722 | mutex_lock(&file->f_pos_lock); | ||
| 723 | } | ||
| 724 | } | ||
| 725 | return v; | ||
| 726 | } | ||
| 727 | |||
| 728 | /* | ||
| 729 | * We only lock f_pos if we have threads or if the file might be | ||
| 730 | * shared with another process. In both cases we'll have an elevated | ||
| 731 | * file count (done either by fdget() or by fork()). | ||
| 732 | */ | ||
| 733 | |||
| 715 | void set_close_on_exec(unsigned int fd, int flag) | 734 | void set_close_on_exec(unsigned int fd, int flag) |
| 716 | { | 735 | { |
| 717 | struct files_struct *files = current->files; | 736 | struct files_struct *files = current->files; |
