diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 43 |
1 files changed, 25 insertions, 18 deletions
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/personality.h> | 24 | #include <linux/personality.h> |
| 25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
| 26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
| 27 | #include <linux/rcupdate.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/unistd.h> | 29 | #include <asm/unistd.h> |
| 29 | 30 | ||
| @@ -842,14 +843,16 @@ int get_unused_fd(void) | |||
| 842 | { | 843 | { |
| 843 | struct files_struct * files = current->files; | 844 | struct files_struct * files = current->files; |
| 844 | int fd, error; | 845 | int fd, error; |
| 846 | struct fdtable *fdt; | ||
| 845 | 847 | ||
| 846 | error = -EMFILE; | 848 | error = -EMFILE; |
| 847 | spin_lock(&files->file_lock); | 849 | spin_lock(&files->file_lock); |
| 848 | 850 | ||
| 849 | repeat: | 851 | repeat: |
| 850 | fd = find_next_zero_bit(files->open_fds->fds_bits, | 852 | fdt = files_fdtable(files); |
| 851 | files->max_fdset, | 853 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, |
| 852 | files->next_fd); | 854 | fdt->max_fdset, |
| 855 | fdt->next_fd); | ||
| 853 | 856 | ||
| 854 | /* | 857 | /* |
| 855 | * N.B. For clone tasks sharing a files structure, this test | 858 | * N.B. For clone tasks sharing a files structure, this test |
| @@ -872,14 +875,14 @@ repeat: | |||
| 872 | goto repeat; | 875 | goto repeat; |
| 873 | } | 876 | } |
| 874 | 877 | ||
| 875 | FD_SET(fd, files->open_fds); | 878 | FD_SET(fd, fdt->open_fds); |
| 876 | FD_CLR(fd, files->close_on_exec); | 879 | FD_CLR(fd, fdt->close_on_exec); |
| 877 | files->next_fd = fd + 1; | 880 | fdt->next_fd = fd + 1; |
| 878 | #if 1 | 881 | #if 1 |
| 879 | /* Sanity check */ | 882 | /* Sanity check */ |
| 880 | if (files->fd[fd] != NULL) { | 883 | if (fdt->fd[fd] != NULL) { |
| 881 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); | 884 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); |
| 882 | files->fd[fd] = NULL; | 885 | fdt->fd[fd] = NULL; |
| 883 | } | 886 | } |
| 884 | #endif | 887 | #endif |
| 885 | error = fd; | 888 | error = fd; |
| @@ -893,9 +896,10 @@ EXPORT_SYMBOL(get_unused_fd); | |||
| 893 | 896 | ||
| 894 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) | 897 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) |
| 895 | { | 898 | { |
| 896 | __FD_CLR(fd, files->open_fds); | 899 | struct fdtable *fdt = files_fdtable(files); |
| 897 | if (fd < files->next_fd) | 900 | __FD_CLR(fd, fdt->open_fds); |
| 898 | files->next_fd = fd; | 901 | if (fd < fdt->next_fd) |
| 902 | fdt->next_fd = fd; | ||
| 899 | } | 903 | } |
| 900 | 904 | ||
| 901 | void fastcall put_unused_fd(unsigned int fd) | 905 | void fastcall put_unused_fd(unsigned int fd) |
| @@ -924,10 +928,11 @@ EXPORT_SYMBOL(put_unused_fd); | |||
| 924 | void fastcall fd_install(unsigned int fd, struct file * file) | 928 | void fastcall fd_install(unsigned int fd, struct file * file) |
| 925 | { | 929 | { |
| 926 | struct files_struct *files = current->files; | 930 | struct files_struct *files = current->files; |
| 931 | struct fdtable *fdt; | ||
| 927 | spin_lock(&files->file_lock); | 932 | spin_lock(&files->file_lock); |
| 928 | if (unlikely(files->fd[fd] != NULL)) | 933 | fdt = files_fdtable(files); |
| 929 | BUG(); | 934 | BUG_ON(fdt->fd[fd] != NULL); |
| 930 | files->fd[fd] = file; | 935 | rcu_assign_pointer(fdt->fd[fd], file); |
| 931 | spin_unlock(&files->file_lock); | 936 | spin_unlock(&files->file_lock); |
| 932 | } | 937 | } |
| 933 | 938 | ||
| @@ -1010,15 +1015,17 @@ asmlinkage long sys_close(unsigned int fd) | |||
| 1010 | { | 1015 | { |
| 1011 | struct file * filp; | 1016 | struct file * filp; |
| 1012 | struct files_struct *files = current->files; | 1017 | struct files_struct *files = current->files; |
| 1018 | struct fdtable *fdt; | ||
| 1013 | 1019 | ||
| 1014 | spin_lock(&files->file_lock); | 1020 | spin_lock(&files->file_lock); |
| 1015 | if (fd >= files->max_fds) | 1021 | fdt = files_fdtable(files); |
| 1022 | if (fd >= fdt->max_fds) | ||
| 1016 | goto out_unlock; | 1023 | goto out_unlock; |
| 1017 | filp = files->fd[fd]; | 1024 | filp = fdt->fd[fd]; |
| 1018 | if (!filp) | 1025 | if (!filp) |
| 1019 | goto out_unlock; | 1026 | goto out_unlock; |
| 1020 | files->fd[fd] = NULL; | 1027 | rcu_assign_pointer(fdt->fd[fd], NULL); |
| 1021 | FD_CLR(fd, files->close_on_exec); | 1028 | FD_CLR(fd, fdt->close_on_exec); |
| 1022 | __put_unused_fd(files, fd); | 1029 | __put_unused_fd(files, fd); |
| 1023 | spin_unlock(&files->file_lock); | 1030 | spin_unlock(&files->file_lock); |
| 1024 | return filp_close(filp, files); | 1031 | return filp_close(filp, files); |
