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>
This commit is contained in:

committed by
H. Peter Anvin

parent
1dce27c5aa
commit
1fd36adcd9
@@ -21,51 +21,43 @@
|
||||
*/
|
||||
#define NR_OPEN_DEFAULT BITS_PER_LONG
|
||||
|
||||
/*
|
||||
* The embedded_fd_set is a small fd_set,
|
||||
* suitable for most tasks (which open <= BITS_PER_LONG files)
|
||||
*/
|
||||
struct embedded_fd_set {
|
||||
unsigned long fds_bits[1];
|
||||
};
|
||||
|
||||
struct fdtable {
|
||||
unsigned int max_fds;
|
||||
struct file __rcu **fd; /* current fd array */
|
||||
fd_set *close_on_exec;
|
||||
fd_set *open_fds;
|
||||
unsigned long *close_on_exec;
|
||||
unsigned long *open_fds;
|
||||
struct rcu_head rcu;
|
||||
struct fdtable *next;
|
||||
};
|
||||
|
||||
static inline void __set_close_on_exec(int fd, struct fdtable *fdt)
|
||||
{
|
||||
FD_SET(fd, fdt->close_on_exec);
|
||||
__set_bit(fd, fdt->close_on_exec);
|
||||
}
|
||||
|
||||
static inline void __clear_close_on_exec(int fd, struct fdtable *fdt)
|
||||
{
|
||||
FD_CLR(fd, fdt->close_on_exec);
|
||||
__clear_bit(fd, fdt->close_on_exec);
|
||||
}
|
||||
|
||||
static inline bool close_on_exec(int fd, const struct fdtable *fdt)
|
||||
{
|
||||
return FD_ISSET(fd, fdt->close_on_exec);
|
||||
return test_bit(fd, fdt->close_on_exec);
|
||||
}
|
||||
|
||||
static inline void __set_open_fd(int fd, struct fdtable *fdt)
|
||||
{
|
||||
FD_SET(fd, fdt->open_fds);
|
||||
__set_bit(fd, fdt->open_fds);
|
||||
}
|
||||
|
||||
static inline void __clear_open_fd(int fd, struct fdtable *fdt)
|
||||
{
|
||||
FD_CLR(fd, fdt->open_fds);
|
||||
__clear_bit(fd, fdt->open_fds);
|
||||
}
|
||||
|
||||
static inline bool fd_is_open(int fd, const struct fdtable *fdt)
|
||||
{
|
||||
return FD_ISSET(fd, fdt->open_fds);
|
||||
return test_bit(fd, fdt->open_fds);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -83,8 +75,8 @@ struct files_struct {
|
||||
*/
|
||||
spinlock_t file_lock ____cacheline_aligned_in_smp;
|
||||
int next_fd;
|
||||
struct embedded_fd_set close_on_exec_init;
|
||||
struct embedded_fd_set open_fds_init;
|
||||
unsigned long close_on_exec_init[1];
|
||||
unsigned long open_fds_init[1];
|
||||
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user