diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/file.c | 56 | ||||
-rw-r--r-- | fs/read_write.c | 16 |
2 files changed, 44 insertions, 28 deletions
@@ -683,35 +683,65 @@ 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); |
712 | } | ||
713 | |||
714 | unsigned long __fdget_pos(unsigned int fd) | ||
715 | { | ||
716 | struct files_struct *files = current->files; | ||
717 | struct file *file; | ||
718 | unsigned long v; | ||
719 | |||
720 | if (atomic_read(&files->count) == 1) { | ||
721 | file = __fcheck_files(files, fd); | ||
722 | v = 0; | ||
723 | } else { | ||
724 | file = __fget(fd, 0); | ||
725 | v = FDPUT_FPUT; | ||
726 | } | ||
727 | if (!file) | ||
728 | return 0; | ||
729 | |||
730 | if (file->f_mode & FMODE_ATOMIC_POS) { | ||
731 | if (file_count(file) > 1) { | ||
732 | v |= FDPUT_POS_UNLOCK; | ||
733 | mutex_lock(&file->f_pos_lock); | ||
734 | } | ||
735 | } | ||
736 | return v | (unsigned long)file; | ||
713 | } | 737 | } |
714 | 738 | ||
739 | /* | ||
740 | * We only lock f_pos if we have threads or if the file might be | ||
741 | * shared with another process. In both cases we'll have an elevated | ||
742 | * file count (done either by fdget() or by fork()). | ||
743 | */ | ||
744 | |||
715 | void set_close_on_exec(unsigned int fd, int flag) | 745 | void set_close_on_exec(unsigned int fd, int flag) |
716 | { | 746 | { |
717 | struct files_struct *files = current->files; | 747 | struct files_struct *files = current->files; |
diff --git a/fs/read_write.c b/fs/read_write.c index 932bb3414a96..54e19b9392dc 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -264,23 +264,9 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence) | |||
264 | } | 264 | } |
265 | EXPORT_SYMBOL(vfs_llseek); | 265 | EXPORT_SYMBOL(vfs_llseek); |
266 | 266 | ||
267 | /* | ||
268 | * We only lock f_pos if we have threads or if the file might be | ||
269 | * shared with another process. In both cases we'll have an elevated | ||
270 | * file count (done either by fdget() or by fork()). | ||
271 | */ | ||
272 | static inline struct fd fdget_pos(int fd) | 267 | static inline struct fd fdget_pos(int fd) |
273 | { | 268 | { |
274 | struct fd f = fdget(fd); | 269 | return __to_fd(__fdget_pos(fd)); |
275 | struct file *file = f.file; | ||
276 | |||
277 | if (file && (file->f_mode & FMODE_ATOMIC_POS)) { | ||
278 | if (file_count(file) > 1) { | ||
279 | f.flags |= FDPUT_POS_UNLOCK; | ||
280 | mutex_lock(&file->f_pos_lock); | ||
281 | } | ||
282 | } | ||
283 | return f; | ||
284 | } | 270 | } |
285 | 271 | ||
286 | static inline void fdput_pos(struct fd f) | 272 | static inline void fdput_pos(struct fd f) |