diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-04 14:54:22 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-10 11:44:42 -0400 |
| commit | bd2a31d522344b3ac2fb680bd2366e77a9bd8209 (patch) | |
| tree | d08be6aea75b2f41bebf516bfc33187d0673bfce | |
| parent | 00e188ef6a7e7bf2883bcffc30d89e98a0bb76b3 (diff) | |
get rid of fget_light()
instead of returning the flags by reference, we can just have the
low-level primitive return those in lower bits of unsigned long,
with struct file * derived from the rest.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/file.c | 56 | ||||
| -rw-r--r-- | fs/read_write.c | 16 | ||||
| -rw-r--r-- | include/linux/file.h | 21 | ||||
| -rw-r--r-- | include/linux/fs.h | 2 |
4 files changed, 56 insertions, 39 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) |
diff --git a/include/linux/file.h b/include/linux/file.h index f2517fa2d610..4d69123377a2 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
| @@ -40,23 +40,24 @@ static inline void fdput(struct fd fd) | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | extern struct file *fget(unsigned int fd); | 42 | extern struct file *fget(unsigned int fd); |
| 43 | extern struct file *fget_light(unsigned int fd, int *fput_needed); | 43 | extern struct file *fget_raw(unsigned int fd); |
| 44 | extern unsigned long __fdget(unsigned int fd); | ||
| 45 | extern unsigned long __fdget_raw(unsigned int fd); | ||
| 46 | extern unsigned long __fdget_pos(unsigned int fd); | ||
| 44 | 47 | ||
| 45 | static inline struct fd fdget(unsigned int fd) | 48 | static inline struct fd __to_fd(unsigned long v) |
| 46 | { | 49 | { |
| 47 | int b; | 50 | return (struct fd){(struct file *)(v & ~3),v & 3}; |
| 48 | struct file *f = fget_light(fd, &b); | ||
| 49 | return (struct fd){f,b}; | ||
| 50 | } | 51 | } |
| 51 | 52 | ||
| 52 | extern struct file *fget_raw(unsigned int fd); | 53 | static inline struct fd fdget(unsigned int fd) |
| 53 | extern struct file *fget_raw_light(unsigned int fd, int *fput_needed); | 54 | { |
| 55 | return __to_fd(__fdget(fd)); | ||
| 56 | } | ||
| 54 | 57 | ||
| 55 | static inline struct fd fdget_raw(unsigned int fd) | 58 | static inline struct fd fdget_raw(unsigned int fd) |
| 56 | { | 59 | { |
| 57 | int b; | 60 | return __to_fd(__fdget_raw(fd)); |
| 58 | struct file *f = fget_raw_light(fd, &b); | ||
| 59 | return (struct fd){f,b}; | ||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); | 63 | extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ebfde04bca06..23b2a35d712e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -812,7 +812,7 @@ struct file { | |||
| 812 | #ifdef CONFIG_DEBUG_WRITECOUNT | 812 | #ifdef CONFIG_DEBUG_WRITECOUNT |
| 813 | unsigned long f_mnt_write_state; | 813 | unsigned long f_mnt_write_state; |
| 814 | #endif | 814 | #endif |
| 815 | }; | 815 | } __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */ |
| 816 | 816 | ||
| 817 | struct file_handle { | 817 | struct file_handle { |
| 818 | __u32 handle_bytes; | 818 | __u32 handle_bytes; |
