Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'stat-cleanups' (clean up copying of stat info to user space)

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

+45 -20
+21
arch/x86/include/asm/stat.h
··· 25 25 unsigned long __unused5; 26 26 }; 27 27 28 + /* We don't need to memset the whole thing just to initialize the padding */ 29 + #define INIT_STRUCT_STAT_PADDING(st) do { \ 30 + st.__unused4 = 0; \ 31 + st.__unused5 = 0; \ 32 + } while (0) 33 + 28 34 #define STAT64_HAS_BROKEN_ST_INO 1 29 35 30 36 /* This matches struct stat64 in glibc2.1, hence the absolutely ··· 69 63 unsigned long long st_ino; 70 64 }; 71 65 66 + /* We don't need to memset the whole thing just to initialize the padding */ 67 + #define INIT_STRUCT_STAT64_PADDING(st) do { \ 68 + memset(&st.__pad0, 0, sizeof(st.__pad0)); \ 69 + memset(&st.__pad3, 0, sizeof(st.__pad3)); \ 70 + } while (0) 71 + 72 72 #else /* __i386__ */ 73 73 74 74 struct stat { ··· 99 87 unsigned long st_ctime_nsec; 100 88 long __unused[3]; 101 89 }; 90 + 91 + /* We don't need to memset the whole thing just to initialize the padding */ 92 + #define INIT_STRUCT_STAT_PADDING(st) do { \ 93 + st.__pad0 = 0; \ 94 + st.__unused[0] = 0; \ 95 + st.__unused[1] = 0; \ 96 + st.__unused[2] = 0; \ 97 + } while (0) 98 + 102 99 #endif 103 100 104 101 /* for 32bit emulation and 32 bit kernels */
+24 -20
fs/stat.c
··· 190 190 191 191 #endif /* __ARCH_WANT_OLD_STAT */ 192 192 193 + #if BITS_PER_LONG == 32 194 + # define choose_32_64(a,b) a 195 + #else 196 + # define choose_32_64(a,b) b 197 + #endif 198 + 199 + #define valid_dev(x) choose_32_64(old_valid_dev,new_valid_dev)(x) 200 + #define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x) 201 + 202 + #ifndef INIT_STRUCT_STAT_PADDING 203 + # define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st)) 204 + #endif 205 + 193 206 static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) 194 207 { 195 208 struct stat tmp; 196 209 197 - #if BITS_PER_LONG == 32 198 - if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) 210 + if (!valid_dev(stat->dev) || !valid_dev(stat->rdev)) 199 211 return -EOVERFLOW; 200 - #else 201 - if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 212 + #if BITS_PER_LONG == 32 213 + if (stat->size > MAX_NON_LFS) 202 214 return -EOVERFLOW; 203 215 #endif 204 216 205 - memset(&tmp, 0, sizeof(tmp)); 206 - #if BITS_PER_LONG == 32 207 - tmp.st_dev = old_encode_dev(stat->dev); 208 - #else 209 - tmp.st_dev = new_encode_dev(stat->dev); 210 - #endif 217 + INIT_STRUCT_STAT_PADDING(tmp); 218 + tmp.st_dev = encode_dev(stat->dev); 211 219 tmp.st_ino = stat->ino; 212 220 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 213 221 return -EOVERFLOW; ··· 225 217 return -EOVERFLOW; 226 218 SET_UID(tmp.st_uid, stat->uid); 227 219 SET_GID(tmp.st_gid, stat->gid); 228 - #if BITS_PER_LONG == 32 229 - tmp.st_rdev = old_encode_dev(stat->rdev); 230 - #else 231 - tmp.st_rdev = new_encode_dev(stat->rdev); 232 - #endif 233 - #if BITS_PER_LONG == 32 234 - if (stat->size > MAX_NON_LFS) 235 - return -EOVERFLOW; 236 - #endif 220 + tmp.st_rdev = encode_dev(stat->rdev); 237 221 tmp.st_size = stat->size; 238 222 tmp.st_atime = stat->atime.tv_sec; 239 223 tmp.st_mtime = stat->mtime.tv_sec; ··· 327 327 /* ---------- LFS-64 ----------- */ 328 328 #ifdef __ARCH_WANT_STAT64 329 329 330 + #ifndef INIT_STRUCT_STAT64_PADDING 331 + # define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st)) 332 + #endif 333 + 330 334 static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) 331 335 { 332 336 struct stat64 tmp; 333 337 334 - memset(&tmp, 0, sizeof(struct stat64)); 338 + INIT_STRUCT_STAT64_PADDING(tmp); 335 339 #ifdef CONFIG_MIPS 336 340 /* mips has weird padding, so we don't get 64 bits there */ 337 341 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))