diff options
| author | David Howells <dhowells@redhat.com> | 2012-02-16 12:49:54 -0500 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2012-02-19 13:30:57 -0500 |
| commit | 1fd36adcd98c14d2fd97f545293c488775cb2823 (patch) | |
| tree | c13ab1934a15aebe0d81601d910ce5a3c6fa2c6f /include/linux | |
| parent | 1dce27c5aa6770e9d195f2bb7db1db3d4dde5591 (diff) | |
Replace the fd_sets in struct fdtable with an array of unsigned longs
Replace the fd_sets in struct fdtable with an array of unsigned longs and then
use the standard non-atomic bit operations rather than the FD_* macros.
This:
(1) Removes the abuses of struct fd_set:
(a) Since we don't want to allocate a full fd_set the vast majority of the
time, we actually, in effect, just allocate a just-big-enough array of
unsigned longs and cast it to an fd_set type - so why bother with the
fd_set at all?
(b) Some places outside of the core fdtable handling code (such as
SELinux) want to look inside the array of unsigned longs hidden inside
the fd_set struct for more efficient iteration over the entire set.
(2) Eliminates the use of FD_*() macros in the kernel completely.
(3) Permits the __FD_*() macros to be deleted entirely where not exposed to
userspace.
Signed-off-by: David Howells <dhowells@redhat.com>
Link: http://lkml.kernel.org/r/20120216174954.23314.48147.stgit@warthog.procyon.org.uk
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/fdtable.h | 28 |
1 files changed, 10 insertions, 18 deletions
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 7675da2c18f7..158a41eed314 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h | |||
| @@ -21,51 +21,43 @@ | |||
| 21 | */ | 21 | */ |
| 22 | #define NR_OPEN_DEFAULT BITS_PER_LONG | 22 | #define NR_OPEN_DEFAULT BITS_PER_LONG |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | * The embedded_fd_set is a small fd_set, | ||
| 26 | * suitable for most tasks (which open <= BITS_PER_LONG files) | ||
| 27 | */ | ||
| 28 | struct embedded_fd_set { | ||
| 29 | unsigned long fds_bits[1]; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct fdtable { | 24 | struct fdtable { |
| 33 | unsigned int max_fds; | 25 | unsigned int max_fds; |
| 34 | struct file __rcu **fd; /* current fd array */ | 26 | struct file __rcu **fd; /* current fd array */ |
| 35 | fd_set *close_on_exec; | 27 | unsigned long *close_on_exec; |
| 36 | fd_set *open_fds; | 28 | unsigned long *open_fds; |
| 37 | struct rcu_head rcu; | 29 | struct rcu_head rcu; |
| 38 | struct fdtable *next; | 30 | struct fdtable *next; |
| 39 | }; | 31 | }; |
| 40 | 32 | ||
| 41 | static inline void __set_close_on_exec(int fd, struct fdtable *fdt) | 33 | static inline void __set_close_on_exec(int fd, struct fdtable *fdt) |
| 42 | { | 34 | { |
| 43 | FD_SET(fd, fdt->close_on_exec); | 35 | __set_bit(fd, fdt->close_on_exec); |
| 44 | } | 36 | } |
| 45 | 37 | ||
| 46 | static inline void __clear_close_on_exec(int fd, struct fdtable *fdt) | 38 | static inline void __clear_close_on_exec(int fd, struct fdtable *fdt) |
| 47 | { | 39 | { |
| 48 | FD_CLR(fd, fdt->close_on_exec); | 40 | __clear_bit(fd, fdt->close_on_exec); |
| 49 | } | 41 | } |
| 50 | 42 | ||
| 51 | static inline bool close_on_exec(int fd, const struct fdtable *fdt) | 43 | static inline bool close_on_exec(int fd, const struct fdtable *fdt) |
| 52 | { | 44 | { |
| 53 | return FD_ISSET(fd, fdt->close_on_exec); | 45 | return test_bit(fd, fdt->close_on_exec); |
| 54 | } | 46 | } |
| 55 | 47 | ||
| 56 | static inline void __set_open_fd(int fd, struct fdtable *fdt) | 48 | static inline void __set_open_fd(int fd, struct fdtable *fdt) |
| 57 | { | 49 | { |
| 58 | FD_SET(fd, fdt->open_fds); | 50 | __set_bit(fd, fdt->open_fds); |
| 59 | } | 51 | } |
| 60 | 52 | ||
| 61 | static inline void __clear_open_fd(int fd, struct fdtable *fdt) | 53 | static inline void __clear_open_fd(int fd, struct fdtable *fdt) |
| 62 | { | 54 | { |
| 63 | FD_CLR(fd, fdt->open_fds); | 55 | __clear_bit(fd, fdt->open_fds); |
| 64 | } | 56 | } |
| 65 | 57 | ||
| 66 | static inline bool fd_is_open(int fd, const struct fdtable *fdt) | 58 | static inline bool fd_is_open(int fd, const struct fdtable *fdt) |
| 67 | { | 59 | { |
| 68 | return FD_ISSET(fd, fdt->open_fds); | 60 | return test_bit(fd, fdt->open_fds); |
| 69 | } | 61 | } |
| 70 | 62 | ||
| 71 | /* | 63 | /* |
| @@ -83,8 +75,8 @@ struct files_struct { | |||
| 83 | */ | 75 | */ |
| 84 | spinlock_t file_lock ____cacheline_aligned_in_smp; | 76 | spinlock_t file_lock ____cacheline_aligned_in_smp; |
| 85 | int next_fd; | 77 | int next_fd; |
| 86 | struct embedded_fd_set close_on_exec_init; | 78 | unsigned long close_on_exec_init[1]; |
| 87 | struct embedded_fd_set open_fds_init; | 79 | unsigned long open_fds_init[1]; |
| 88 | struct file __rcu * fd_array[NR_OPEN_DEFAULT]; | 80 | struct file __rcu * fd_array[NR_OPEN_DEFAULT]; |
| 89 | }; | 81 | }; |
| 90 | 82 | ||
