aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/file.c56
-rw-r--r--fs/read_write.c16
2 files changed, 44 insertions, 28 deletions
diff --git a/fs/file.c b/fs/file.c
index db25c2bdfe46..60a45e9f5323 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -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 */
686struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) 686static 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}
704struct file *fget_light(unsigned int fd, int *fput_needed) 703unsigned 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}
708EXPORT_SYMBOL(fget_light); 707EXPORT_SYMBOL(__fdget);
709 708
710struct file *fget_raw_light(unsigned int fd, int *fput_needed) 709unsigned long __fdget_raw(unsigned int fd)
711{ 710{
712 return __fget_light(fd, 0, fput_needed); 711 return __fget_light(fd, 0);
712}
713
714unsigned 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
715void set_close_on_exec(unsigned int fd, int flag) 745void 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}
265EXPORT_SYMBOL(vfs_llseek); 265EXPORT_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 */
272static inline struct fd fdget_pos(int fd) 267static 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
286static inline void fdput_pos(struct fd f) 272static inline void fdput_pos(struct fd f)