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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-v4.4-rc4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull ftrace/recordmcount fix from Steven Rostedt:
"Russell King was reporting lots of warnings when he compiled his
kernel with ftrace enabled. With some investigation it was discovered
that it was his compile setup. He was using ccache with hard links,
which allowed recordmcount to process the same .o twice. When this
happens, recordmcount will detect that it was already done and give a
warning about it.

Russell fixed this by having recordmcount detect that the object file
has more than one hard link, and if it does, it unlinks the object
file after it maps it and processes then. This appears to fix the
issue.

As you did not like the fact that recordmcount modified the file in
place and thought that it should do the modifications in memory and
then write it out to disk and move it over the old file to prevent
other more subtle issues like the one above, a second patch is added
on top of Russell's to do just that. Luckily the original code had
write and lseek wrappers that I was able to modify to not do inplace
writes, but simply keep track of the changes made in memory. When a
write is made, a "update" flag is set, and at the end of processing,
if the update is set, then it writes the file with changes out to a
new file, and then renames it over the original one.

The file descriptor is still passed to the write and lseek wrappers
because removing that would cause the change to be more intrusive.
That can be removed in a follow up cleanup patch that can wait till
the next merge window"

* tag 'trace-v4.4-rc4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
ftrace/scripts: Have recordmcount copy the object file
scripts: recordmcount: break hardlinks

+113 -24
+113 -24
scripts/recordmcount.c
··· 48 48 49 49 static int fd_map; /* File descriptor for file being modified. */ 50 50 static int mmap_failed; /* Boolean flag. */ 51 - static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ 52 51 static char gpfx; /* prefix for global symbol name (sometimes '_') */ 53 52 static struct stat sb; /* Remember .st_size, etc. */ 54 53 static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ 55 54 static const char *altmcount; /* alternate mcount symbol name */ 56 55 static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */ 56 + static void *file_map; /* pointer of the mapped file */ 57 + static void *file_end; /* pointer to the end of the mapped file */ 58 + static int file_updated; /* flag to state file was changed */ 59 + static void *file_ptr; /* current file pointer location */ 60 + static void *file_append; /* added to the end of the file */ 61 + static size_t file_append_size; /* how much is added to end of file */ 57 62 58 63 /* setjmp() return values */ 59 64 enum { ··· 72 67 cleanup(void) 73 68 { 74 69 if (!mmap_failed) 75 - munmap(ehdr_curr, sb.st_size); 70 + munmap(file_map, sb.st_size); 76 71 else 77 - free(ehdr_curr); 78 - close(fd_map); 72 + free(file_map); 73 + file_map = NULL; 74 + free(file_append); 75 + file_append = NULL; 76 + file_append_size = 0; 77 + file_updated = 0; 79 78 } 80 79 81 80 static void __attribute__((noreturn)) ··· 101 92 static off_t 102 93 ulseek(int const fd, off_t const offset, int const whence) 103 94 { 104 - off_t const w = lseek(fd, offset, whence); 105 - if (w == (off_t)-1) { 106 - perror("lseek"); 95 + switch (whence) { 96 + case SEEK_SET: 97 + file_ptr = file_map + offset; 98 + break; 99 + case SEEK_CUR: 100 + file_ptr += offset; 101 + break; 102 + case SEEK_END: 103 + file_ptr = file_map + (sb.st_size - offset); 104 + break; 105 + } 106 + if (file_ptr < file_map) { 107 + fprintf(stderr, "lseek: seek before file\n"); 107 108 fail_file(); 108 109 } 109 - return w; 110 + return file_ptr - file_map; 110 111 } 111 112 112 113 static size_t ··· 133 114 static size_t 134 115 uwrite(int const fd, void const *const buf, size_t const count) 135 116 { 136 - size_t const n = write(fd, buf, count); 137 - if (n != count) { 138 - perror("write"); 139 - fail_file(); 117 + size_t cnt = count; 118 + off_t idx = 0; 119 + 120 + file_updated = 1; 121 + 122 + if (file_ptr + count >= file_end) { 123 + off_t aoffset = (file_ptr + count) - file_end; 124 + 125 + if (aoffset > file_append_size) { 126 + file_append = realloc(file_append, aoffset); 127 + file_append_size = aoffset; 128 + } 129 + if (!file_append) { 130 + perror("write"); 131 + fail_file(); 132 + } 133 + if (file_ptr < file_end) { 134 + cnt = file_end - file_ptr; 135 + } else { 136 + cnt = 0; 137 + idx = aoffset - count; 138 + } 140 139 } 141 - return n; 140 + 141 + if (cnt) 142 + memcpy(file_ptr, buf, cnt); 143 + 144 + if (cnt < count) 145 + memcpy(file_append + idx, buf + cnt, count - cnt); 146 + 147 + file_ptr += count; 148 + return count; 142 149 } 143 150 144 151 static void * ··· 237 192 */ 238 193 static void *mmap_file(char const *fname) 239 194 { 240 - void *addr; 241 - 242 - fd_map = open(fname, O_RDWR); 195 + fd_map = open(fname, O_RDONLY); 243 196 if (fd_map < 0 || fstat(fd_map, &sb) < 0) { 244 197 perror(fname); 245 198 fail_file(); ··· 246 203 fprintf(stderr, "not a regular file: %s\n", fname); 247 204 fail_file(); 248 205 } 249 - addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, 250 - fd_map, 0); 206 + file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, 207 + fd_map, 0); 251 208 mmap_failed = 0; 252 - if (addr == MAP_FAILED) { 209 + if (file_map == MAP_FAILED) { 253 210 mmap_failed = 1; 254 - addr = umalloc(sb.st_size); 255 - uread(fd_map, addr, sb.st_size); 211 + file_map = umalloc(sb.st_size); 212 + uread(fd_map, file_map, sb.st_size); 256 213 } 257 - return addr; 214 + close(fd_map); 215 + 216 + file_end = file_map + sb.st_size; 217 + 218 + return file_map; 219 + } 220 + 221 + static void write_file(const char *fname) 222 + { 223 + char tmp_file[strlen(fname) + 4]; 224 + size_t n; 225 + 226 + if (!file_updated) 227 + return; 228 + 229 + sprintf(tmp_file, "%s.rc", fname); 230 + 231 + /* 232 + * After reading the entire file into memory, delete it 233 + * and write it back, to prevent weird side effects of modifying 234 + * an object file in place. 235 + */ 236 + fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode); 237 + if (fd_map < 0) { 238 + perror(fname); 239 + fail_file(); 240 + } 241 + n = write(fd_map, file_map, sb.st_size); 242 + if (n != sb.st_size) { 243 + perror("write"); 244 + fail_file(); 245 + } 246 + if (file_append_size) { 247 + n = write(fd_map, file_append, file_append_size); 248 + if (n != file_append_size) { 249 + perror("write"); 250 + fail_file(); 251 + } 252 + } 253 + close(fd_map); 254 + if (rename(tmp_file, fname) < 0) { 255 + perror(fname); 256 + fail_file(); 257 + } 258 258 } 259 259 260 260 /* w8rev, w8nat, ...: Handle endianness. */ ··· 404 318 Elf32_Ehdr *const ehdr = mmap_file(fname); 405 319 unsigned int reltype = 0; 406 320 407 - ehdr_curr = ehdr; 408 321 w = w4nat; 409 322 w2 = w2nat; 410 323 w8 = w8nat; ··· 526 441 } 527 442 } /* end switch */ 528 443 444 + write_file(fname); 529 445 cleanup(); 530 446 } 531 447 ··· 579 493 case SJ_SETJMP: /* normal sequence */ 580 494 /* Avoid problems if early cleanup() */ 581 495 fd_map = -1; 582 - ehdr_curr = NULL; 583 496 mmap_failed = 1; 497 + file_map = NULL; 498 + file_ptr = NULL; 499 + file_updated = 0; 584 500 do_file(file); 585 501 break; 586 502 case SJ_FAIL: /* error in do_file or below */ 503 + sprintf("%s: failed\n", file); 587 504 ++n_error; 588 505 break; 589 506 case SJ_SUCCEED: /* premature success */