diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-06 18:02:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-06 18:02:40 -0700 |
commit | 8529f613b6945f4b5bd8c1b69e42aa1cc51b2eb6 (patch) | |
tree | c8d29b5c266d90ddbaf3982b3863d64dc2be2ca4 /fs/stat.c | |
parent | a52dd971f947893bc7735396c74cfa591f0a7558 (diff) | |
download | lwn-8529f613b6945f4b5bd8c1b69e42aa1cc51b2eb6.tar.gz lwn-8529f613b6945f4b5bd8c1b69e42aa1cc51b2eb6.zip |
vfs: don't force a big memset of stat data just to clear padding fields
Admittedly this is something that the compiler should be able to just do
for us, but gcc just isn't that smart. And trying to use a structure
initializer (which would get us the right semantics) ends up resulting
in gcc allocating stack space for _two_ 'struct stat', and then copying
one into the other.
So do it by hand - just have a per-architecture macro that initializes
the padding fields. And if the architecture doesn't provide one, fall
back to the old behavior of just doing the whole memset() first.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/stat.c')
-rw-r--r-- | fs/stat.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/stat.c b/fs/stat.c index 2b5d55eb9d9a..b30ac60291e2 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -199,6 +199,10 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat #define valid_dev(x) choose_32_64(old_valid_dev,new_valid_dev)(x) #define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x) +#ifndef INIT_STRUCT_STAT_PADDING +# define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st)) +#endif + static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) { struct stat tmp; @@ -210,7 +214,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) return -EOVERFLOW; #endif - memset(&tmp, 0, sizeof(tmp)); + INIT_STRUCT_STAT_PADDING(tmp); tmp.st_dev = encode_dev(stat->dev); tmp.st_ino = stat->ino; if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) @@ -323,11 +327,15 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf, /* ---------- LFS-64 ----------- */ #ifdef __ARCH_WANT_STAT64 +#ifndef INIT_STRUCT_STAT64_PADDING +# define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st)) +#endif + static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) { struct stat64 tmp; - memset(&tmp, 0, sizeof(struct stat64)); + INIT_STRUCT_STAT64_PADDING(tmp); #ifdef CONFIG_MIPS /* mips has weird padding, so we don't get 64 bits there */ if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) |