From 8b3d1cda4f5ff0d7c2ae910ea8fd03493996912f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 7 Feb 2012 21:09:05 -0800 Subject: posix_types: Remove fd_set macros includes a set of macros that operate on file descriptors. Way long ago those were exported to user space, but nowadays they are #ifdef __KERNEL__. However, they are nothing but standard (nonatomic) bit operations, and we already have optimized versions of bit operations in the kernel. We can't include in but we can move the definitions to and define them there in terms of standard kernel bitops. [ v2: folds the following fixes in: a) Stray space in __FD_SET(), reported by Andrew Morton b) #include needed for memset(), reported by Tony Luck ] Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/r/1328677745-20121-22-git-send-email-hpa@zytor.com Cc: Arnd Bergmann Cc: Tony Luck Cc: Andrew Morton --- include/linux/time.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'include/linux') diff --git a/include/linux/time.h b/include/linux/time.h index b3061782dec3..93277a0b2293 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -4,8 +4,11 @@ #include #ifdef __KERNEL__ +# include # include +# include # include +# include # include #endif @@ -256,6 +259,27 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns); a->tv_nsec = ns; } + +static inline void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + __set_bit(__fd, __fdsetp->fds_bits); +} + +static inline void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + __clear_bit(__fd, __fdsetp->fds_bits); +} + +static inline int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__fdsetp) +{ + return test_bit(__fd, __fdsetp->fds_bits); +} + +static inline void __FD_ZERO(__kernel_fd_set *__fdsetp) +{ + memset(__fdsetp->fds_bits, 0, sizeof __fdsetp->fds_bits); +} + #endif /* __KERNEL__ */ #define NFDBITS __NFDBITS -- cgit v1.2.3 From 1dce27c5aa6770e9d195f2bb7db1db3d4dde5591 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 16 Feb 2012 17:49:42 +0000 Subject: Wrap accesses to the fd_sets in struct fdtable Wrap accesses to the fd_sets in struct fdtable (for recording open files and close-on-exec flags) so that we can move away from using fd_sets since we abuse the fd_set structs by not allocating the full-sized structure under normal circumstances and by non-core code looking at the internals of the fd_sets. The first abuse means that use of FD_ZERO() on these fd_sets is not permitted, since that cannot be told about their abnormal lengths. This introduces six wrapper functions for setting, clearing and testing close-on-exec flags and fd-is-open flags: void __set_close_on_exec(int fd, struct fdtable *fdt); void __clear_close_on_exec(int fd, struct fdtable *fdt); bool close_on_exec(int fd, const struct fdtable *fdt); void __set_open_fd(int fd, struct fdtable *fdt); void __clear_open_fd(int fd, struct fdtable *fdt); bool fd_is_open(int fd, const struct fdtable *fdt); Note that I've prepended '__' to the names of the set/clear functions because they require the caller to hold a lock to use them. Note also that I haven't added wrappers for looking behind the scenes at the the array. Possibly that should exist too. Signed-off-by: David Howells Link: http://lkml.kernel.org/r/20120216174942.23314.1364.stgit@warthog.procyon.org.uk Signed-off-by: H. Peter Anvin Cc: Al Viro --- include/linux/fdtable.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include/linux') diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 82163c4b32c9..7675da2c18f7 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -38,6 +38,36 @@ struct fdtable { struct fdtable *next; }; +static inline void __set_close_on_exec(int fd, struct fdtable *fdt) +{ + FD_SET(fd, fdt->close_on_exec); +} + +static inline void __clear_close_on_exec(int fd, struct fdtable *fdt) +{ + FD_CLR(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); +} + +static inline void __set_open_fd(int fd, struct fdtable *fdt) +{ + FD_SET(fd, fdt->open_fds); +} + +static inline void __clear_open_fd(int fd, struct fdtable *fdt) +{ + FD_CLR(fd, fdt->open_fds); +} + +static inline bool fd_is_open(int fd, const struct fdtable *fdt) +{ + return FD_ISSET(fd, fdt->open_fds); +} + /* * Open file table structure */ -- cgit v1.2.3 From 1fd36adcd98c14d2fd97f545293c488775cb2823 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 16 Feb 2012 17:49:54 +0000 Subject: 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 Link: http://lkml.kernel.org/r/20120216174954.23314.48147.stgit@warthog.procyon.org.uk Signed-off-by: H. Peter Anvin Cc: Al Viro --- include/linux/fdtable.h | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'include/linux') 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 @@ */ #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]; }; -- cgit v1.2.3 From cf420048b3b2af9ce928d35cc5455c646c9dd2f7 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 16 Feb 2012 17:50:06 +0000 Subject: Delete the __FD_*() funcs for operating on fd_set from linux/time.h Delete the __FD_*() functions for operating on fd_set structs from linux/time.h as they're no longer used within the kernel with the preceding patch and are not exported to userspace. Whilst linux/time.h *does* export the FD_*() equivalents as wrappers around __FD_*(), userspace provides its own definition of __FD_*(). Note that the definition of FD_ZERO() in linux/time.h may not be used with the fd_sets associated with struct fdtable as the fd_set may have been allocated in a truncated fashion. Signed-off-by: David Howells Link: http://lkml.kernel.org/r/20120216175006.23314.18984.stgit@warthog.procyon.org.uk Signed-off-by: H. Peter Anvin Cc: Al Viro --- include/linux/time.h | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'include/linux') diff --git a/include/linux/time.h b/include/linux/time.h index 93277a0b2293..9f43487facdf 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -4,11 +4,8 @@ #include #ifdef __KERNEL__ -# include # include -# include # include -# include # include #endif @@ -260,26 +257,6 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) a->tv_nsec = ns; } -static inline void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) -{ - __set_bit(__fd, __fdsetp->fds_bits); -} - -static inline void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) -{ - __clear_bit(__fd, __fdsetp->fds_bits); -} - -static inline int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__fdsetp) -{ - return test_bit(__fd, __fdsetp->fds_bits); -} - -static inline void __FD_ZERO(__kernel_fd_set *__fdsetp) -{ - memset(__fdsetp->fds_bits, 0, sizeof __fdsetp->fds_bits); -} - #endif /* __KERNEL__ */ #define NFDBITS __NFDBITS -- cgit v1.2.3 From d8e5ddef21df05bc2a14d8c0e287cbf083da60a3 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 6 Feb 2012 16:36:48 -0800 Subject: sysinfo: Move struct sysinfo to a separate header file struct sysinfo is just about the only thing exported to userspace from , so move it into a separate header file with a residual #include in . Originally-by: H. J. Lu Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/n/tip-4pr1xnnksprt7t0h3w5fw4rv@git.kernel.org --- include/linux/Kbuild | 1 + include/linux/kernel.h | 21 ++------------------- include/linux/sysinfo.h | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 include/linux/sysinfo.h (limited to 'include/linux') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index c94e71781b79..844608677665 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -355,6 +355,7 @@ header-y += suspend_ioctls.h header-y += swab.h header-y += synclink.h header-y += sysctl.h +header-y += sysinfo.h header-y += taskstats.h header-y += tcp.h header-y += telephony.h diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e8343422240a..dc6a50f88ca7 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -1,6 +1,8 @@ #ifndef _LINUX_KERNEL_H #define _LINUX_KERNEL_H +#include + /* * 'kernel.h' contains some often-used function prototypes etc */ @@ -745,27 +747,8 @@ extern int __build_bug_on_failed; # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD #endif -struct sysinfo; extern int do_sysinfo(struct sysinfo *info); #endif /* __KERNEL__ */ -#define SI_LOAD_SHIFT 16 -struct sysinfo { - long uptime; /* Seconds since boot */ - unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ - unsigned long totalram; /* Total usable main memory size */ - unsigned long freeram; /* Available memory size */ - unsigned long sharedram; /* Amount of shared memory */ - unsigned long bufferram; /* Memory used by buffers */ - unsigned long totalswap; /* Total swap space size */ - unsigned long freeswap; /* swap space still available */ - unsigned short procs; /* Number of current processes */ - unsigned short pad; /* explicit padding for m68k */ - unsigned long totalhigh; /* Total high memory size */ - unsigned long freehigh; /* Available high memory size */ - unsigned int mem_unit; /* Memory unit size in bytes */ - char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ -}; - #endif diff --git a/include/linux/sysinfo.h b/include/linux/sysinfo.h new file mode 100644 index 000000000000..ec4fc228ac0a --- /dev/null +++ b/include/linux/sysinfo.h @@ -0,0 +1,22 @@ +#ifndef _LINUX_SYSINFO_H +#define _LINUX_SYSINFO_H + +#define SI_LOAD_SHIFT 16 +struct sysinfo { + long uptime; /* Seconds since boot */ + unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ + unsigned long totalram; /* Total usable main memory size */ + unsigned long freeram; /* Available memory size */ + unsigned long sharedram; /* Amount of shared memory */ + unsigned long bufferram; /* Memory used by buffers */ + unsigned long totalswap; /* Total swap space size */ + unsigned long freeswap; /* swap space still available */ + unsigned short procs; /* Number of current processes */ + unsigned short pad; /* explicit padding for m68k */ + unsigned long totalhigh; /* Total high memory size */ + unsigned long freehigh; /* Available high memory size */ + unsigned int mem_unit; /* Memory unit size in bytes */ + char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +}; + +#endif /* _LINUX_SYSINFO_H */ -- cgit v1.2.3 From 109a1f32d0d3e23545f0286f2d6e0a80298f629d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 10 Feb 2012 13:58:56 -0800 Subject: sysinfo: Use explicit types in Change to use explicitly sized types. Replace long/unsigned long with __kernel_[u]long_t so that a non-legacy 32-bit ABI running on a 64-bit kernel can export those as 64-bit types. Originally-by: H. J. Lu Signed-off-by: H. Peter Anvin --- include/linux/sysinfo.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sysinfo.h b/include/linux/sysinfo.h index ec4fc228ac0a..934335a22522 100644 --- a/include/linux/sysinfo.h +++ b/include/linux/sysinfo.h @@ -1,22 +1,24 @@ #ifndef _LINUX_SYSINFO_H #define _LINUX_SYSINFO_H +#include + #define SI_LOAD_SHIFT 16 struct sysinfo { - long uptime; /* Seconds since boot */ - unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ - unsigned long totalram; /* Total usable main memory size */ - unsigned long freeram; /* Available memory size */ - unsigned long sharedram; /* Amount of shared memory */ - unsigned long bufferram; /* Memory used by buffers */ - unsigned long totalswap; /* Total swap space size */ - unsigned long freeswap; /* swap space still available */ - unsigned short procs; /* Number of current processes */ - unsigned short pad; /* explicit padding for m68k */ - unsigned long totalhigh; /* Total high memory size */ - unsigned long freehigh; /* Available high memory size */ - unsigned int mem_unit; /* Memory unit size in bytes */ - char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ + __kernel_long_t uptime; /* Seconds since boot */ + __kernel_ulong_t loads[3]; /* 1, 5, and 15 minute load averages */ + __kernel_ulong_t totalram; /* Total usable main memory size */ + __kernel_ulong_t freeram; /* Available memory size */ + __kernel_ulong_t sharedram; /* Amount of shared memory */ + __kernel_ulong_t bufferram; /* Memory used by buffers */ + __kernel_ulong_t totalswap; /* Total swap space size */ + __kernel_ulong_t freeswap; /* swap space still available */ + __u16 procs; /* Number of current processes */ + __u16 pad; /* Explicit padding for m68k */ + __kernel_ulong_t totalhigh; /* Total high memory size */ + __kernel_ulong_t freehigh; /* Available high memory size */ + __u32 mem_unit; /* Memory unit size in bytes */ + char _f[20-2*sizeof(__kernel_ulong_t)-sizeof(__u32)]; /* Padding: libc5 uses this.. */ }; #endif /* _LINUX_SYSINFO_H */ -- cgit v1.2.3 From 45e877812926c69d643d6274347f79513a4ee934 Mon Sep 17 00:00:00 2001 From: "H. J. Lu" Date: Fri, 10 Feb 2012 14:04:27 -0800 Subject: compat: Introduce COMPAT_USE_64BIT_TIME Allow a compatibility ABI to use a 64-bit time_t and 64-bit members in struct timeval and struct timespec to avoid the Y2038 problem. This will be used for the x32 ABI. Signed-off-by: H. Peter Anvin --- include/linux/compat.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/compat.h b/include/linux/compat.h index 41c9f6515f46..1be91c048249 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -19,6 +19,10 @@ #include #include +#ifndef COMPAT_USE_64BIT_TIME +#define COMPAT_USE_64BIT_TIME 0 +#endif + #define compat_jiffies_to_clock_t(x) \ (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) -- cgit v1.2.3 From 6684ba202b5ab2f36d574c72fe50c207d99b3e35 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 19 Feb 2012 17:38:00 -0800 Subject: compat: Add helper functions to read/write struct timeval, timespec Add helper functions to read and write struct timeval and struct timespec from userspace. We already had helper functions for reading and writing struct compat_timespec; add a set of functions to do the same with struct timeval, and add a second suite of functions which can be sensitive to COMPAT_USE_64BIT_TIME and access either 32- or 64-bit time structures. This also exports these helper functions to modules. Rename the existing inlines for converting between struct compat_timeval and native struct timespec so we can have a saner naming convention for the exported functions. Suggested-by: Linus Torvalds Signed-off-by: H. Peter Anvin --- include/linux/compat.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include/linux') diff --git a/include/linux/compat.h b/include/linux/compat.h index 1be91c048249..a82e452bbdb9 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -87,10 +87,26 @@ typedef struct { compat_sigset_word sig[_COMPAT_NSIG_WORDS]; } compat_sigset_t; +/* + * These functions operate strictly on struct compat_time* + */ extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); +extern int get_compat_timeval(struct timeval *, + const struct compat_timeval __user *); +extern int put_compat_timeval(const struct timeval *, + struct compat_timeval __user *); +/* + * These functions operate on 32- or 64-bit specs depending on + * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments and the + * naming as compat_get/put_ rather than get/put_compat_. + */ +extern int compat_get_timespec(struct timespec *, const void __user *); +extern int compat_put_timespec(const struct timespec *, void __user *); +extern int compat_get_timeval(struct timeval *, const void __user *); +extern int compat_put_timeval(const struct timeval *, void __user *); struct compat_iovec { compat_uptr_t iov_base; -- cgit v1.2.3 From ff88943a1471440cc6be7a11a942a5a8232bee61 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 14 Feb 2012 12:58:56 -0800 Subject: aio: Use __kernel_ulong_t to define aio_context_t Rather than using "unsigned long" which is ABI-dependent, use __kernel_ulong_t to define the externally visible type aio_context_t. Note: the change in this form will cause unsigned long/unsigned int differences on existing ABIs. If that is unacceptable we may have to define a new type. Signed-off-by: H. Peter Anvin Cc: Benjamin LaHaise --- include/linux/aio_abi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h index 2c8731664180..86fa7a71336a 100644 --- a/include/linux/aio_abi.h +++ b/include/linux/aio_abi.h @@ -30,7 +30,7 @@ #include #include -typedef unsigned long aio_context_t; +typedef __kernel_ulong_t aio_context_t; enum { IOCB_CMD_PREAD = 0, -- cgit v1.2.3