Merge branch 'stat-cleanups' (clean up copying of stat info to user space)
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 May 2012 15:41:38 +0000 (08:41 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 May 2012 15:41:38 +0000 (08:41 -0700)
This makes cp_new_stat() a bit more readable, and avoids having to
memset() the whole structure just to fill in a couple of padding fields.

This is another result of me looking at code generation of functions
that show up high on certain kernel profiles, and just going "Oh, let's
just clean that up".

Architectures that don't supply the #define to fill just the padding
fields will still fall back to memset().

* stat-cleanups:
  vfs: don't force a big memset of stat data just to clear padding fields
  vfs: de-crapify "cp_new_stat()" function

arch/x86/include/asm/stat.h
fs/stat.c

index e0b1d9bbcbc66b2b1717949537795c2688cd09bc..7b3ddc348585f0c8b4cc0afe63b6ac36206217d3 100644 (file)
@@ -25,6 +25,12 @@ struct stat {
        unsigned long  __unused5;
 };
 
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do {      \
+       st.__unused4 = 0;                       \
+       st.__unused5 = 0;                       \
+} while (0)
+
 #define STAT64_HAS_BROKEN_ST_INO       1
 
 /* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -63,6 +69,12 @@ struct stat64 {
        unsigned long long      st_ino;
 };
 
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT64_PADDING(st) do {            \
+       memset(&st.__pad0, 0, sizeof(st.__pad0));       \
+       memset(&st.__pad3, 0, sizeof(st.__pad3));       \
+} while (0)
+
 #else /* __i386__ */
 
 struct stat {
@@ -87,6 +99,15 @@ struct stat {
        unsigned long   st_ctime_nsec;
        long            __unused[3];
 };
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do {      \
+       st.__pad0 = 0;                          \
+       st.__unused[0] = 0;                     \
+       st.__unused[1] = 0;                     \
+       st.__unused[2] = 0;                     \
+} while (0)
+
 #endif
 
 /* for 32bit emulation and 32 bit kernels */
index c733dc5753aea129a1e5deb76bf48d0cb640d6e3..b30ac60291e273bbdf833f4f51da20032bd2f587 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -190,24 +190,32 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
 
 #endif /* __ARCH_WANT_OLD_STAT */
 
+#if BITS_PER_LONG == 32
+#  define choose_32_64(a,b) a
+#else
+#  define choose_32_64(a,b) b
+#endif
+
+#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;
 
-#if BITS_PER_LONG == 32
-       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+       if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
                return -EOVERFLOW;
-#else
-       if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
+#if BITS_PER_LONG == 32
+       if (stat->size > MAX_NON_LFS)
                return -EOVERFLOW;
 #endif
 
-       memset(&tmp, 0, sizeof(tmp));
-#if BITS_PER_LONG == 32
-       tmp.st_dev = old_encode_dev(stat->dev);
-#else
-       tmp.st_dev = new_encode_dev(stat->dev);
-#endif
+       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)
                return -EOVERFLOW;
@@ -217,15 +225,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
                return -EOVERFLOW;
        SET_UID(tmp.st_uid, stat->uid);
        SET_GID(tmp.st_gid, stat->gid);
-#if BITS_PER_LONG == 32
-       tmp.st_rdev = old_encode_dev(stat->rdev);
-#else
-       tmp.st_rdev = new_encode_dev(stat->rdev);
-#endif
-#if BITS_PER_LONG == 32
-       if (stat->size > MAX_NON_LFS)
-               return -EOVERFLOW;
-#endif 
+       tmp.st_rdev = encode_dev(stat->rdev);
        tmp.st_size = stat->size;
        tmp.st_atime = stat->atime.tv_sec;
        tmp.st_mtime = stat->mtime.tv_sec;
@@ -327,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))