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

drm: Add puts callback for the coredump printer

Add a puts function for the coredump printer to bypass printf()
for constant strings for a speed boost. Reorganize the
coredump printf callback to share as much code as possible.

v2: Try to reuse code between print and puts as suggested by
Chris Wilson

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>

authored by

Jordan Crouse and committed by
Rob Clark
5dc634bd 4538d732

+56 -40
+54 -40
drivers/gpu/drm/drm_print.c
··· 30 30 #include <drm/drmP.h> 31 31 #include <drm/drm_print.h> 32 32 33 - void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf) 33 + void __drm_puts_coredump(struct drm_printer *p, const char *str) 34 34 { 35 35 struct drm_print_iterator *iterator = p->arg; 36 36 ssize_t len; ··· 38 38 if (!iterator->remain) 39 39 return; 40 40 41 - /* Figure out how big the string will be */ 42 - len = snprintf(NULL, 0, "%pV", vaf); 43 - 44 41 if (iterator->offset < iterator->start) { 45 - char *buf; 46 42 ssize_t copy; 43 + 44 + len = strlen(str); 47 45 48 46 if (iterator->offset + len <= iterator->start) { 49 47 iterator->offset += len; 50 48 return; 51 49 } 52 - 53 - /* Print the string into a temporary buffer */ 54 - buf = kmalloc(len + 1, 55 - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 56 - if (!buf) 57 - return; 58 - 59 - snprintf(buf, len + 1, "%pV", vaf); 60 50 61 51 copy = len - (iterator->start - iterator->offset); 62 52 ··· 55 65 56 66 /* Copy out the bit of the string that we need */ 57 67 memcpy(iterator->data, 58 - buf + (iterator->start - iterator->offset), copy); 68 + str + (iterator->start - iterator->offset), copy); 59 69 60 70 iterator->offset = iterator->start + copy; 61 71 iterator->remain -= copy; 62 - 63 - kfree(buf); 64 72 } else { 65 - char *buf; 66 73 ssize_t pos = iterator->offset - iterator->start; 67 74 68 - if (len < iterator->remain) { 69 - snprintf(((char *) iterator->data) + pos, 70 - iterator->remain, "%pV", vaf); 75 + len = min_t(ssize_t, strlen(str), iterator->remain); 71 76 72 - iterator->offset += len; 73 - iterator->remain -= len; 77 + memcpy(iterator->data + pos, str, len); 74 78 75 - return; 76 - } 77 - 78 - /* Print the string into a temporary buffer */ 79 - buf = kmalloc(len + 1, 80 - GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 81 - if (!buf) 82 - return; 83 - 84 - snprintf(buf, len + 1, "%pV", vaf); 85 - 86 - /* Copy out the remaining bits */ 87 - memcpy(iterator->data + pos, buf, iterator->remain); 88 - 89 - iterator->offset += iterator->remain; 90 - iterator->remain = 0; 91 - 92 - kfree(buf); 79 + iterator->offset += len; 80 + iterator->remain -= len; 93 81 } 82 + } 83 + EXPORT_SYMBOL(__drm_puts_coredump); 84 + 85 + void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf) 86 + { 87 + struct drm_print_iterator *iterator = p->arg; 88 + size_t len; 89 + char *buf; 90 + 91 + if (!iterator->remain) 92 + return; 93 + 94 + /* Figure out how big the string will be */ 95 + len = snprintf(NULL, 0, "%pV", vaf); 96 + 97 + /* This is the easiest path, we've already advanced beyond the offset */ 98 + if (iterator->offset + len <= iterator->start) { 99 + iterator->offset += len; 100 + return; 101 + } 102 + 103 + /* Then check if we can directly copy into the target buffer */ 104 + if ((iterator->offset >= iterator->start) && (len < iterator->remain)) { 105 + ssize_t pos = iterator->offset - iterator->start; 106 + 107 + snprintf(((char *) iterator->data) + pos, 108 + iterator->remain, "%pV", vaf); 109 + 110 + iterator->offset += len; 111 + iterator->remain -= len; 112 + 113 + return; 114 + } 115 + 116 + /* 117 + * Finally, hit the slow path and make a temporary string to copy over 118 + * using _drm_puts_coredump 119 + */ 120 + buf = kmalloc(len + 1, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 121 + if (!buf) 122 + return; 123 + 124 + snprintf(buf, len + 1, "%pV", vaf); 125 + __drm_puts_coredump(p, (const char *) buf); 126 + 127 + kfree(buf); 94 128 } 95 129 EXPORT_SYMBOL(__drm_printfn_coredump); 96 130
+2
include/drm/drm_print.h
··· 75 75 }; 76 76 77 77 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf); 78 + void __drm_puts_coredump(struct drm_printer *p, const char *str); 78 79 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); 79 80 void __drm_puts_seq_file(struct drm_printer *p, const char *str); 80 81 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); ··· 164 163 { 165 164 struct drm_printer p = { 166 165 .printfn = __drm_printfn_coredump, 166 + .puts = __drm_puts_coredump, 167 167 .arg = iter, 168 168 }; 169 169