diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig.debug | 16 | ||||
| -rw-r--r-- | lib/Kconfig.kgdb | 24 | ||||
| -rw-r--r-- | lib/bug.c | 2 | ||||
| -rw-r--r-- | lib/crc32.c | 26 | ||||
| -rw-r--r-- | lib/dynamic_debug.c | 2 | ||||
| -rw-r--r-- | lib/gen_crc32table.c | 47 | ||||
| -rw-r--r-- | lib/hexdump.c | 54 | ||||
| -rw-r--r-- | lib/idr.c | 2 | ||||
| -rw-r--r-- | lib/kobject.c | 115 | ||||
| -rw-r--r-- | lib/kobject_uevent.c | 109 | ||||
| -rw-r--r-- | lib/kref.c | 15 | ||||
| -rw-r--r-- | lib/vsprintf.c | 69 |
12 files changed, 376 insertions, 105 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index d85be90d5888..231208948363 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -1039,10 +1039,10 @@ config DYNAMIC_DEBUG | |||
| 1039 | 1039 | ||
| 1040 | Usage: | 1040 | Usage: |
| 1041 | 1041 | ||
| 1042 | Dynamic debugging is controlled via the 'dynamic_debug/ddebug' file, | 1042 | Dynamic debugging is controlled via the 'dynamic_debug/control' file, |
| 1043 | which is contained in the 'debugfs' filesystem. Thus, the debugfs | 1043 | which is contained in the 'debugfs' filesystem. Thus, the debugfs |
| 1044 | filesystem must first be mounted before making use of this feature. | 1044 | filesystem must first be mounted before making use of this feature. |
| 1045 | We refer the control file as: <debugfs>/dynamic_debug/ddebug. This | 1045 | We refer the control file as: <debugfs>/dynamic_debug/control. This |
| 1046 | file contains a list of the debug statements that can be enabled. The | 1046 | file contains a list of the debug statements that can be enabled. The |
| 1047 | format for each line of the file is: | 1047 | format for each line of the file is: |
| 1048 | 1048 | ||
| @@ -1057,7 +1057,7 @@ config DYNAMIC_DEBUG | |||
| 1057 | 1057 | ||
| 1058 | From a live system: | 1058 | From a live system: |
| 1059 | 1059 | ||
| 1060 | nullarbor:~ # cat <debugfs>/dynamic_debug/ddebug | 1060 | nullarbor:~ # cat <debugfs>/dynamic_debug/control |
| 1061 | # filename:lineno [module]function flags format | 1061 | # filename:lineno [module]function flags format |
| 1062 | fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012" | 1062 | fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012" |
| 1063 | fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012" | 1063 | fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012" |
| @@ -1067,23 +1067,23 @@ config DYNAMIC_DEBUG | |||
| 1067 | 1067 | ||
| 1068 | // enable the message at line 1603 of file svcsock.c | 1068 | // enable the message at line 1603 of file svcsock.c |
| 1069 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > | 1069 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > |
| 1070 | <debugfs>/dynamic_debug/ddebug | 1070 | <debugfs>/dynamic_debug/control |
| 1071 | 1071 | ||
| 1072 | // enable all the messages in file svcsock.c | 1072 | // enable all the messages in file svcsock.c |
| 1073 | nullarbor:~ # echo -n 'file svcsock.c +p' > | 1073 | nullarbor:~ # echo -n 'file svcsock.c +p' > |
| 1074 | <debugfs>/dynamic_debug/ddebug | 1074 | <debugfs>/dynamic_debug/control |
| 1075 | 1075 | ||
| 1076 | // enable all the messages in the NFS server module | 1076 | // enable all the messages in the NFS server module |
| 1077 | nullarbor:~ # echo -n 'module nfsd +p' > | 1077 | nullarbor:~ # echo -n 'module nfsd +p' > |
| 1078 | <debugfs>/dynamic_debug/ddebug | 1078 | <debugfs>/dynamic_debug/control |
| 1079 | 1079 | ||
| 1080 | // enable all 12 messages in the function svc_process() | 1080 | // enable all 12 messages in the function svc_process() |
| 1081 | nullarbor:~ # echo -n 'func svc_process +p' > | 1081 | nullarbor:~ # echo -n 'func svc_process +p' > |
| 1082 | <debugfs>/dynamic_debug/ddebug | 1082 | <debugfs>/dynamic_debug/control |
| 1083 | 1083 | ||
| 1084 | // disable all 12 messages in the function svc_process() | 1084 | // disable all 12 messages in the function svc_process() |
| 1085 | nullarbor:~ # echo -n 'func svc_process -p' > | 1085 | nullarbor:~ # echo -n 'func svc_process -p' > |
| 1086 | <debugfs>/dynamic_debug/ddebug | 1086 | <debugfs>/dynamic_debug/control |
| 1087 | 1087 | ||
| 1088 | See Documentation/dynamic-debug-howto.txt for additional information. | 1088 | See Documentation/dynamic-debug-howto.txt for additional information. |
| 1089 | 1089 | ||
diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index 9b5d1d7f2ef7..43cb93fa2651 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb | |||
| @@ -3,7 +3,7 @@ config HAVE_ARCH_KGDB | |||
| 3 | bool | 3 | bool |
| 4 | 4 | ||
| 5 | menuconfig KGDB | 5 | menuconfig KGDB |
| 6 | bool "KGDB: kernel debugging with remote gdb" | 6 | bool "KGDB: kernel debugger" |
| 7 | depends on HAVE_ARCH_KGDB | 7 | depends on HAVE_ARCH_KGDB |
| 8 | depends on DEBUG_KERNEL && EXPERIMENTAL | 8 | depends on DEBUG_KERNEL && EXPERIMENTAL |
| 9 | help | 9 | help |
| @@ -57,4 +57,26 @@ config KGDB_TESTS_BOOT_STRING | |||
| 57 | information about other strings you could use beyond the | 57 | information about other strings you could use beyond the |
| 58 | default of V1F100. | 58 | default of V1F100. |
| 59 | 59 | ||
| 60 | config KGDB_LOW_LEVEL_TRAP | ||
| 61 | bool "KGDB: Allow debugging with traps in notifiers" | ||
| 62 | depends on X86 || MIPS | ||
| 63 | default n | ||
| 64 | help | ||
| 65 | This will add an extra call back to kgdb for the breakpoint | ||
| 66 | exception handler on which will will allow kgdb to step | ||
| 67 | through a notify handler. | ||
| 68 | |||
| 69 | config KGDB_KDB | ||
| 70 | bool "KGDB_KDB: include kdb frontend for kgdb" | ||
| 71 | default n | ||
| 72 | help | ||
| 73 | KDB frontend for kernel | ||
| 74 | |||
| 75 | config KDB_KEYBOARD | ||
| 76 | bool "KGDB_KDB: keyboard as input device" | ||
| 77 | depends on VT && KGDB_KDB | ||
| 78 | default n | ||
| 79 | help | ||
| 80 | KDB can use a PS/2 type keyboard for an input device | ||
| 81 | |||
| 60 | endif # KGDB | 82 | endif # KGDB |
| @@ -165,7 +165,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) | |||
| 165 | (void *)bugaddr); | 165 | (void *)bugaddr); |
| 166 | 166 | ||
| 167 | show_regs(regs); | 167 | show_regs(regs); |
| 168 | add_taint(TAINT_WARN); | 168 | add_taint(BUG_GET_TAINT(bug)); |
| 169 | return BUG_TRAP_TYPE_WARN; | 169 | return BUG_TRAP_TYPE_WARN; |
| 170 | } | 170 | } |
| 171 | 171 | ||
diff --git a/lib/crc32.c b/lib/crc32.c index bc5b936e9142..3087ed899ee3 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
| @@ -48,12 +48,20 @@ MODULE_LICENSE("GPL"); | |||
| 48 | #if CRC_LE_BITS == 8 || CRC_BE_BITS == 8 | 48 | #if CRC_LE_BITS == 8 || CRC_BE_BITS == 8 |
| 49 | 49 | ||
| 50 | static inline u32 | 50 | static inline u32 |
| 51 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab) | 51 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) |
| 52 | { | 52 | { |
| 53 | # ifdef __LITTLE_ENDIAN | 53 | # if __BYTE_ORDER == __LITTLE_ENDIAN |
| 54 | # define DO_CRC(x) crc = tab[(crc ^ (x)) & 255 ] ^ (crc >> 8) | 54 | # define DO_CRC(x) crc = tab[0][(crc ^ (x)) & 255] ^ (crc >> 8) |
| 55 | # define DO_CRC4 crc = tab[3][(crc) & 255] ^ \ | ||
| 56 | tab[2][(crc >> 8) & 255] ^ \ | ||
| 57 | tab[1][(crc >> 16) & 255] ^ \ | ||
| 58 | tab[0][(crc >> 24) & 255] | ||
| 55 | # else | 59 | # else |
| 56 | # define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8) | 60 | # define DO_CRC(x) crc = tab[0][((crc >> 24) ^ (x)) & 255] ^ (crc << 8) |
| 61 | # define DO_CRC4 crc = tab[0][(crc) & 255] ^ \ | ||
| 62 | tab[1][(crc >> 8) & 255] ^ \ | ||
| 63 | tab[2][(crc >> 16) & 255] ^ \ | ||
| 64 | tab[3][(crc >> 24) & 255] | ||
| 57 | # endif | 65 | # endif |
| 58 | const u32 *b; | 66 | const u32 *b; |
| 59 | size_t rem_len; | 67 | size_t rem_len; |
| @@ -70,10 +78,7 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab) | |||
| 70 | b = (const u32 *)buf; | 78 | b = (const u32 *)buf; |
| 71 | for (--b; len; --len) { | 79 | for (--b; len; --len) { |
| 72 | crc ^= *++b; /* use pre increment for speed */ | 80 | crc ^= *++b; /* use pre increment for speed */ |
| 73 | DO_CRC(0); | 81 | DO_CRC4; |
| 74 | DO_CRC(0); | ||
| 75 | DO_CRC(0); | ||
| 76 | DO_CRC(0); | ||
| 77 | } | 82 | } |
| 78 | len = rem_len; | 83 | len = rem_len; |
| 79 | /* And the last few bytes */ | 84 | /* And the last few bytes */ |
| @@ -85,6 +90,7 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab) | |||
| 85 | } | 90 | } |
| 86 | return crc; | 91 | return crc; |
| 87 | #undef DO_CRC | 92 | #undef DO_CRC |
| 93 | #undef DO_CRC4 | ||
| 88 | } | 94 | } |
| 89 | #endif | 95 | #endif |
| 90 | /** | 96 | /** |
| @@ -117,7 +123,7 @@ u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | |||
| 117 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | 123 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) |
| 118 | { | 124 | { |
| 119 | # if CRC_LE_BITS == 8 | 125 | # if CRC_LE_BITS == 8 |
| 120 | const u32 *tab = crc32table_le; | 126 | const u32 (*tab)[] = crc32table_le; |
| 121 | 127 | ||
| 122 | crc = __cpu_to_le32(crc); | 128 | crc = __cpu_to_le32(crc); |
| 123 | crc = crc32_body(crc, p, len, tab); | 129 | crc = crc32_body(crc, p, len, tab); |
| @@ -174,7 +180,7 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | |||
| 174 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | 180 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) |
| 175 | { | 181 | { |
| 176 | # if CRC_BE_BITS == 8 | 182 | # if CRC_BE_BITS == 8 |
| 177 | const u32 *tab = crc32table_be; | 183 | const u32 (*tab)[] = crc32table_be; |
| 178 | 184 | ||
| 179 | crc = __cpu_to_be32(crc); | 185 | crc = __cpu_to_be32(crc); |
| 180 | crc = crc32_body(crc, p, len, tab); | 186 | crc = crc32_body(crc, p, len, tab); |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index d6b8b9b1abfe..3df8eb17a607 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
| @@ -456,7 +456,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, | |||
| 456 | __func__, (int)len); | 456 | __func__, (int)len); |
| 457 | 457 | ||
| 458 | nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); | 458 | nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); |
| 459 | if (nwords < 0) | 459 | if (nwords <= 0) |
| 460 | return -EINVAL; | 460 | return -EINVAL; |
| 461 | if (ddebug_parse_query(words, nwords-1, &query)) | 461 | if (ddebug_parse_query(words, nwords-1, &query)) |
| 462 | return -EINVAL; | 462 | return -EINVAL; |
diff --git a/lib/gen_crc32table.c b/lib/gen_crc32table.c index bea5d97df991..85d0e412a04f 100644 --- a/lib/gen_crc32table.c +++ b/lib/gen_crc32table.c | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #define LE_TABLE_SIZE (1 << CRC_LE_BITS) | 7 | #define LE_TABLE_SIZE (1 << CRC_LE_BITS) |
| 8 | #define BE_TABLE_SIZE (1 << CRC_BE_BITS) | 8 | #define BE_TABLE_SIZE (1 << CRC_BE_BITS) |
| 9 | 9 | ||
| 10 | static uint32_t crc32table_le[LE_TABLE_SIZE]; | 10 | static uint32_t crc32table_le[4][LE_TABLE_SIZE]; |
| 11 | static uint32_t crc32table_be[BE_TABLE_SIZE]; | 11 | static uint32_t crc32table_be[4][BE_TABLE_SIZE]; |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | * crc32init_le() - allocate and initialize LE table data | 14 | * crc32init_le() - allocate and initialize LE table data |
| @@ -22,12 +22,19 @@ static void crc32init_le(void) | |||
| 22 | unsigned i, j; | 22 | unsigned i, j; |
| 23 | uint32_t crc = 1; | 23 | uint32_t crc = 1; |
| 24 | 24 | ||
| 25 | crc32table_le[0] = 0; | 25 | crc32table_le[0][0] = 0; |
| 26 | 26 | ||
| 27 | for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) { | 27 | for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) { |
| 28 | crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); | 28 | crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); |
| 29 | for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) | 29 | for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) |
| 30 | crc32table_le[i + j] = crc ^ crc32table_le[j]; | 30 | crc32table_le[0][i + j] = crc ^ crc32table_le[0][j]; |
| 31 | } | ||
| 32 | for (i = 0; i < LE_TABLE_SIZE; i++) { | ||
| 33 | crc = crc32table_le[0][i]; | ||
| 34 | for (j = 1; j < 4; j++) { | ||
| 35 | crc = crc32table_le[0][crc & 0xff] ^ (crc >> 8); | ||
| 36 | crc32table_le[j][i] = crc; | ||
| 37 | } | ||
| 31 | } | 38 | } |
| 32 | } | 39 | } |
| 33 | 40 | ||
| @@ -39,25 +46,35 @@ static void crc32init_be(void) | |||
| 39 | unsigned i, j; | 46 | unsigned i, j; |
| 40 | uint32_t crc = 0x80000000; | 47 | uint32_t crc = 0x80000000; |
| 41 | 48 | ||
| 42 | crc32table_be[0] = 0; | 49 | crc32table_be[0][0] = 0; |
| 43 | 50 | ||
| 44 | for (i = 1; i < BE_TABLE_SIZE; i <<= 1) { | 51 | for (i = 1; i < BE_TABLE_SIZE; i <<= 1) { |
| 45 | crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); | 52 | crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); |
| 46 | for (j = 0; j < i; j++) | 53 | for (j = 0; j < i; j++) |
| 47 | crc32table_be[i + j] = crc ^ crc32table_be[j]; | 54 | crc32table_be[0][i + j] = crc ^ crc32table_be[0][j]; |
| 55 | } | ||
| 56 | for (i = 0; i < BE_TABLE_SIZE; i++) { | ||
| 57 | crc = crc32table_be[0][i]; | ||
| 58 | for (j = 1; j < 4; j++) { | ||
| 59 | crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8); | ||
| 60 | crc32table_be[j][i] = crc; | ||
| 61 | } | ||
| 48 | } | 62 | } |
| 49 | } | 63 | } |
| 50 | 64 | ||
| 51 | static void output_table(uint32_t table[], int len, char *trans) | 65 | static void output_table(uint32_t table[4][256], int len, char *trans) |
| 52 | { | 66 | { |
| 53 | int i; | 67 | int i, j; |
| 54 | 68 | ||
| 55 | for (i = 0; i < len - 1; i++) { | 69 | for (j = 0 ; j < 4; j++) { |
| 56 | if (i % ENTRIES_PER_LINE == 0) | 70 | printf("{"); |
| 57 | printf("\n"); | 71 | for (i = 0; i < len - 1; i++) { |
| 58 | printf("%s(0x%8.8xL), ", trans, table[i]); | 72 | if (i % ENTRIES_PER_LINE == 0) |
| 73 | printf("\n"); | ||
| 74 | printf("%s(0x%8.8xL), ", trans, table[j][i]); | ||
| 75 | } | ||
| 76 | printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]); | ||
| 59 | } | 77 | } |
| 60 | printf("%s(0x%8.8xL)\n", trans, table[len - 1]); | ||
| 61 | } | 78 | } |
| 62 | 79 | ||
| 63 | int main(int argc, char** argv) | 80 | int main(int argc, char** argv) |
| @@ -66,14 +83,14 @@ int main(int argc, char** argv) | |||
| 66 | 83 | ||
| 67 | if (CRC_LE_BITS > 1) { | 84 | if (CRC_LE_BITS > 1) { |
| 68 | crc32init_le(); | 85 | crc32init_le(); |
| 69 | printf("static const u32 crc32table_le[] = {"); | 86 | printf("static const u32 crc32table_le[4][256] = {"); |
| 70 | output_table(crc32table_le, LE_TABLE_SIZE, "tole"); | 87 | output_table(crc32table_le, LE_TABLE_SIZE, "tole"); |
| 71 | printf("};\n"); | 88 | printf("};\n"); |
| 72 | } | 89 | } |
| 73 | 90 | ||
| 74 | if (CRC_BE_BITS > 1) { | 91 | if (CRC_BE_BITS > 1) { |
| 75 | crc32init_be(); | 92 | crc32init_be(); |
| 76 | printf("static const u32 crc32table_be[] = {"); | 93 | printf("static const u32 crc32table_be[4][256] = {"); |
| 77 | output_table(crc32table_be, BE_TABLE_SIZE, "tobe"); | 94 | output_table(crc32table_be, BE_TABLE_SIZE, "tobe"); |
| 78 | printf("};\n"); | 95 | printf("};\n"); |
| 79 | } | 96 | } |
diff --git a/lib/hexdump.c b/lib/hexdump.c index 39af2560f765..5d7a4802c562 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c | |||
| @@ -16,6 +16,24 @@ const char hex_asc[] = "0123456789abcdef"; | |||
| 16 | EXPORT_SYMBOL(hex_asc); | 16 | EXPORT_SYMBOL(hex_asc); |
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | * hex_to_bin - convert a hex digit to its real value | ||
| 20 | * @ch: ascii character represents hex digit | ||
| 21 | * | ||
| 22 | * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad | ||
| 23 | * input. | ||
| 24 | */ | ||
| 25 | int hex_to_bin(char ch) | ||
| 26 | { | ||
| 27 | if ((ch >= '0') && (ch <= '9')) | ||
| 28 | return ch - '0'; | ||
| 29 | ch = tolower(ch); | ||
| 30 | if ((ch >= 'a') && (ch <= 'f')) | ||
| 31 | return ch - 'a' + 10; | ||
| 32 | return -1; | ||
| 33 | } | ||
| 34 | EXPORT_SYMBOL(hex_to_bin); | ||
| 35 | |||
| 36 | /** | ||
| 19 | * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory | 37 | * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory |
| 20 | * @buf: data blob to dump | 38 | * @buf: data blob to dump |
| 21 | * @len: number of bytes in the @buf | 39 | * @len: number of bytes in the @buf |
| @@ -34,7 +52,7 @@ EXPORT_SYMBOL(hex_asc); | |||
| 34 | * | 52 | * |
| 35 | * E.g.: | 53 | * E.g.: |
| 36 | * hex_dump_to_buffer(frame->data, frame->len, 16, 1, | 54 | * hex_dump_to_buffer(frame->data, frame->len, 16, 1, |
| 37 | * linebuf, sizeof(linebuf), 1); | 55 | * linebuf, sizeof(linebuf), true); |
| 38 | * | 56 | * |
| 39 | * example output buffer: | 57 | * example output buffer: |
| 40 | * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO | 58 | * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO |
| @@ -65,8 +83,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
| 65 | 83 | ||
| 66 | for (j = 0; j < ngroups; j++) | 84 | for (j = 0; j < ngroups; j++) |
| 67 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 85 | lx += scnprintf(linebuf + lx, linebuflen - lx, |
| 68 | "%s%16.16llx", j ? " " : "", | 86 | "%s%16.16llx", j ? " " : "", |
| 69 | (unsigned long long)*(ptr8 + j)); | 87 | (unsigned long long)*(ptr8 + j)); |
| 70 | ascii_column = 17 * ngroups + 2; | 88 | ascii_column = 17 * ngroups + 2; |
| 71 | break; | 89 | break; |
| 72 | } | 90 | } |
| @@ -77,7 +95,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
| 77 | 95 | ||
| 78 | for (j = 0; j < ngroups; j++) | 96 | for (j = 0; j < ngroups; j++) |
| 79 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 97 | lx += scnprintf(linebuf + lx, linebuflen - lx, |
| 80 | "%s%8.8x", j ? " " : "", *(ptr4 + j)); | 98 | "%s%8.8x", j ? " " : "", *(ptr4 + j)); |
| 81 | ascii_column = 9 * ngroups + 2; | 99 | ascii_column = 9 * ngroups + 2; |
| 82 | break; | 100 | break; |
| 83 | } | 101 | } |
| @@ -88,7 +106,7 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
| 88 | 106 | ||
| 89 | for (j = 0; j < ngroups; j++) | 107 | for (j = 0; j < ngroups; j++) |
| 90 | lx += scnprintf(linebuf + lx, linebuflen - lx, | 108 | lx += scnprintf(linebuf + lx, linebuflen - lx, |
| 91 | "%s%4.4x", j ? " " : "", *(ptr2 + j)); | 109 | "%s%4.4x", j ? " " : "", *(ptr2 + j)); |
| 92 | ascii_column = 5 * ngroups + 2; | 110 | ascii_column = 5 * ngroups + 2; |
| 93 | break; | 111 | break; |
| 94 | } | 112 | } |
| @@ -111,9 +129,10 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, | |||
| 111 | 129 | ||
| 112 | while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) | 130 | while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) |
| 113 | linebuf[lx++] = ' '; | 131 | linebuf[lx++] = ' '; |
| 114 | for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) | 132 | for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) { |
| 115 | linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j] | 133 | ch = ptr[j]; |
| 116 | : '.'; | 134 | linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; |
| 135 | } | ||
| 117 | nil: | 136 | nil: |
| 118 | linebuf[lx++] = '\0'; | 137 | linebuf[lx++] = '\0'; |
| 119 | } | 138 | } |
| @@ -143,7 +162,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); | |||
| 143 | * | 162 | * |
| 144 | * E.g.: | 163 | * E.g.: |
| 145 | * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, | 164 | * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, |
| 146 | * 16, 1, frame->data, frame->len, 1); | 165 | * 16, 1, frame->data, frame->len, true); |
| 147 | * | 166 | * |
| 148 | * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode: | 167 | * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode: |
| 149 | * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO | 168 | * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO |
| @@ -151,12 +170,12 @@ EXPORT_SYMBOL(hex_dump_to_buffer); | |||
| 151 | * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~. | 170 | * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~. |
| 152 | */ | 171 | */ |
| 153 | void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, | 172 | void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, |
| 154 | int rowsize, int groupsize, | 173 | int rowsize, int groupsize, |
| 155 | const void *buf, size_t len, bool ascii) | 174 | const void *buf, size_t len, bool ascii) |
| 156 | { | 175 | { |
| 157 | const u8 *ptr = buf; | 176 | const u8 *ptr = buf; |
| 158 | int i, linelen, remaining = len; | 177 | int i, linelen, remaining = len; |
| 159 | unsigned char linebuf[200]; | 178 | unsigned char linebuf[32 * 3 + 2 + 32 + 1]; |
| 160 | 179 | ||
| 161 | if (rowsize != 16 && rowsize != 32) | 180 | if (rowsize != 16 && rowsize != 32) |
| 162 | rowsize = 16; | 181 | rowsize = 16; |
| @@ -164,13 +183,14 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, | |||
| 164 | for (i = 0; i < len; i += rowsize) { | 183 | for (i = 0; i < len; i += rowsize) { |
| 165 | linelen = min(remaining, rowsize); | 184 | linelen = min(remaining, rowsize); |
| 166 | remaining -= rowsize; | 185 | remaining -= rowsize; |
| 186 | |||
| 167 | hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, | 187 | hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, |
| 168 | linebuf, sizeof(linebuf), ascii); | 188 | linebuf, sizeof(linebuf), ascii); |
| 169 | 189 | ||
| 170 | switch (prefix_type) { | 190 | switch (prefix_type) { |
| 171 | case DUMP_PREFIX_ADDRESS: | 191 | case DUMP_PREFIX_ADDRESS: |
| 172 | printk("%s%s%*p: %s\n", level, prefix_str, | 192 | printk("%s%s%p: %s\n", |
| 173 | (int)(2 * sizeof(void *)), ptr + i, linebuf); | 193 | level, prefix_str, ptr + i, linebuf); |
| 174 | break; | 194 | break; |
| 175 | case DUMP_PREFIX_OFFSET: | 195 | case DUMP_PREFIX_OFFSET: |
| 176 | printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf); | 196 | printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf); |
| @@ -196,9 +216,9 @@ EXPORT_SYMBOL(print_hex_dump); | |||
| 196 | * rowsize of 16, groupsize of 1, and ASCII output included. | 216 | * rowsize of 16, groupsize of 1, and ASCII output included. |
| 197 | */ | 217 | */ |
| 198 | void print_hex_dump_bytes(const char *prefix_str, int prefix_type, | 218 | void print_hex_dump_bytes(const char *prefix_str, int prefix_type, |
| 199 | const void *buf, size_t len) | 219 | const void *buf, size_t len) |
| 200 | { | 220 | { |
| 201 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1, | 221 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1, |
| 202 | buf, len, 1); | 222 | buf, len, true); |
| 203 | } | 223 | } |
| 204 | EXPORT_SYMBOL(print_hex_dump_bytes); | 224 | EXPORT_SYMBOL(print_hex_dump_bytes); |
| @@ -623,7 +623,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
| 623 | } | 623 | } |
| 624 | return NULL; | 624 | return NULL; |
| 625 | } | 625 | } |
| 626 | 626 | EXPORT_SYMBOL(idr_get_next); | |
| 627 | 627 | ||
| 628 | 628 | ||
| 629 | /** | 629 | /** |
diff --git a/lib/kobject.c b/lib/kobject.c index 8115eb1bbf4d..f07c57252e82 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -850,6 +850,121 @@ struct kset *kset_create_and_add(const char *name, | |||
| 850 | } | 850 | } |
| 851 | EXPORT_SYMBOL_GPL(kset_create_and_add); | 851 | EXPORT_SYMBOL_GPL(kset_create_and_add); |
| 852 | 852 | ||
| 853 | |||
| 854 | static DEFINE_SPINLOCK(kobj_ns_type_lock); | ||
| 855 | static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES]; | ||
| 856 | |||
| 857 | int kobj_ns_type_register(const struct kobj_ns_type_operations *ops) | ||
| 858 | { | ||
| 859 | enum kobj_ns_type type = ops->type; | ||
| 860 | int error; | ||
| 861 | |||
| 862 | spin_lock(&kobj_ns_type_lock); | ||
| 863 | |||
| 864 | error = -EINVAL; | ||
| 865 | if (type >= KOBJ_NS_TYPES) | ||
| 866 | goto out; | ||
| 867 | |||
| 868 | error = -EINVAL; | ||
| 869 | if (type <= KOBJ_NS_TYPE_NONE) | ||
| 870 | goto out; | ||
| 871 | |||
| 872 | error = -EBUSY; | ||
| 873 | if (kobj_ns_ops_tbl[type]) | ||
| 874 | goto out; | ||
| 875 | |||
| 876 | error = 0; | ||
| 877 | kobj_ns_ops_tbl[type] = ops; | ||
| 878 | |||
| 879 | out: | ||
| 880 | spin_unlock(&kobj_ns_type_lock); | ||
| 881 | return error; | ||
| 882 | } | ||
| 883 | |||
| 884 | int kobj_ns_type_registered(enum kobj_ns_type type) | ||
| 885 | { | ||
| 886 | int registered = 0; | ||
| 887 | |||
| 888 | spin_lock(&kobj_ns_type_lock); | ||
| 889 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES)) | ||
| 890 | registered = kobj_ns_ops_tbl[type] != NULL; | ||
| 891 | spin_unlock(&kobj_ns_type_lock); | ||
| 892 | |||
| 893 | return registered; | ||
| 894 | } | ||
| 895 | |||
| 896 | const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent) | ||
| 897 | { | ||
| 898 | const struct kobj_ns_type_operations *ops = NULL; | ||
| 899 | |||
| 900 | if (parent && parent->ktype->child_ns_type) | ||
| 901 | ops = parent->ktype->child_ns_type(parent); | ||
| 902 | |||
| 903 | return ops; | ||
| 904 | } | ||
| 905 | |||
| 906 | const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj) | ||
| 907 | { | ||
| 908 | return kobj_child_ns_ops(kobj->parent); | ||
| 909 | } | ||
| 910 | |||
| 911 | |||
| 912 | const void *kobj_ns_current(enum kobj_ns_type type) | ||
| 913 | { | ||
| 914 | const void *ns = NULL; | ||
| 915 | |||
| 916 | spin_lock(&kobj_ns_type_lock); | ||
| 917 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
| 918 | kobj_ns_ops_tbl[type]) | ||
| 919 | ns = kobj_ns_ops_tbl[type]->current_ns(); | ||
| 920 | spin_unlock(&kobj_ns_type_lock); | ||
| 921 | |||
| 922 | return ns; | ||
| 923 | } | ||
| 924 | |||
| 925 | const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk) | ||
| 926 | { | ||
| 927 | const void *ns = NULL; | ||
| 928 | |||
| 929 | spin_lock(&kobj_ns_type_lock); | ||
| 930 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
| 931 | kobj_ns_ops_tbl[type]) | ||
| 932 | ns = kobj_ns_ops_tbl[type]->netlink_ns(sk); | ||
| 933 | spin_unlock(&kobj_ns_type_lock); | ||
| 934 | |||
| 935 | return ns; | ||
| 936 | } | ||
| 937 | |||
| 938 | const void *kobj_ns_initial(enum kobj_ns_type type) | ||
| 939 | { | ||
| 940 | const void *ns = NULL; | ||
| 941 | |||
| 942 | spin_lock(&kobj_ns_type_lock); | ||
| 943 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
| 944 | kobj_ns_ops_tbl[type]) | ||
| 945 | ns = kobj_ns_ops_tbl[type]->initial_ns(); | ||
| 946 | spin_unlock(&kobj_ns_type_lock); | ||
| 947 | |||
| 948 | return ns; | ||
| 949 | } | ||
| 950 | |||
| 951 | /* | ||
| 952 | * kobj_ns_exit - invalidate a namespace tag | ||
| 953 | * | ||
| 954 | * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET) | ||
| 955 | * @ns: the actual namespace being invalidated | ||
| 956 | * | ||
| 957 | * This is called when a tag is no longer valid. For instance, | ||
| 958 | * when a network namespace exits, it uses this helper to | ||
| 959 | * make sure no sb's sysfs_info points to the now-invalidated | ||
| 960 | * netns. | ||
| 961 | */ | ||
| 962 | void kobj_ns_exit(enum kobj_ns_type type, const void *ns) | ||
| 963 | { | ||
| 964 | sysfs_exit_ns(type, ns); | ||
| 965 | } | ||
| 966 | |||
| 967 | |||
| 853 | EXPORT_SYMBOL(kobject_get); | 968 | EXPORT_SYMBOL(kobject_get); |
| 854 | EXPORT_SYMBOL(kobject_put); | 969 | EXPORT_SYMBOL(kobject_put); |
| 855 | EXPORT_SYMBOL(kobject_del); | 970 | EXPORT_SYMBOL(kobject_del); |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 7b48d44ced6e..59c15511d58a 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
| @@ -19,18 +19,24 @@ | |||
| 19 | #include <linux/kobject.h> | 19 | #include <linux/kobject.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | 22 | #include <linux/user_namespace.h> | |
| 23 | #include <linux/socket.h> | 23 | #include <linux/socket.h> |
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <linux/netlink.h> | 25 | #include <linux/netlink.h> |
| 26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
| 27 | #include <net/net_namespace.h> | ||
| 27 | 28 | ||
| 28 | 29 | ||
| 29 | u64 uevent_seqnum; | 30 | u64 uevent_seqnum; |
| 30 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; | 31 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; |
| 31 | static DEFINE_SPINLOCK(sequence_lock); | 32 | static DEFINE_SPINLOCK(sequence_lock); |
| 32 | #if defined(CONFIG_NET) | 33 | #ifdef CONFIG_NET |
| 33 | static struct sock *uevent_sock; | 34 | struct uevent_sock { |
| 35 | struct list_head list; | ||
| 36 | struct sock *sk; | ||
| 37 | }; | ||
| 38 | static LIST_HEAD(uevent_sock_list); | ||
| 39 | static DEFINE_MUTEX(uevent_sock_mutex); | ||
| 34 | #endif | 40 | #endif |
| 35 | 41 | ||
| 36 | /* the strings here must match the enum in include/linux/kobject.h */ | 42 | /* the strings here must match the enum in include/linux/kobject.h */ |
| @@ -77,6 +83,37 @@ out: | |||
| 77 | return ret; | 83 | return ret; |
| 78 | } | 84 | } |
| 79 | 85 | ||
| 86 | static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data) | ||
| 87 | { | ||
| 88 | struct kobject *kobj = data; | ||
| 89 | const struct kobj_ns_type_operations *ops; | ||
| 90 | |||
| 91 | ops = kobj_ns_ops(kobj); | ||
| 92 | if (ops) { | ||
| 93 | const void *sock_ns, *ns; | ||
| 94 | ns = kobj->ktype->namespace(kobj); | ||
| 95 | sock_ns = ops->netlink_ns(dsk); | ||
| 96 | return sock_ns != ns; | ||
| 97 | } | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int kobj_usermode_filter(struct kobject *kobj) | ||
| 103 | { | ||
| 104 | const struct kobj_ns_type_operations *ops; | ||
| 105 | |||
| 106 | ops = kobj_ns_ops(kobj); | ||
| 107 | if (ops) { | ||
| 108 | const void *init_ns, *ns; | ||
| 109 | ns = kobj->ktype->namespace(kobj); | ||
| 110 | init_ns = ops->initial_ns(); | ||
| 111 | return ns != init_ns; | ||
| 112 | } | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 80 | /** | 117 | /** |
| 81 | * kobject_uevent_env - send an uevent with environmental data | 118 | * kobject_uevent_env - send an uevent with environmental data |
| 82 | * | 119 | * |
| @@ -100,6 +137,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 100 | u64 seq; | 137 | u64 seq; |
| 101 | int i = 0; | 138 | int i = 0; |
| 102 | int retval = 0; | 139 | int retval = 0; |
| 140 | #ifdef CONFIG_NET | ||
| 141 | struct uevent_sock *ue_sk; | ||
| 142 | #endif | ||
| 103 | 143 | ||
| 104 | pr_debug("kobject: '%s' (%p): %s\n", | 144 | pr_debug("kobject: '%s' (%p): %s\n", |
| 105 | kobject_name(kobj), kobj, __func__); | 145 | kobject_name(kobj), kobj, __func__); |
| @@ -211,7 +251,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 211 | 251 | ||
| 212 | #if defined(CONFIG_NET) | 252 | #if defined(CONFIG_NET) |
| 213 | /* send netlink message */ | 253 | /* send netlink message */ |
| 214 | if (uevent_sock) { | 254 | mutex_lock(&uevent_sock_mutex); |
| 255 | list_for_each_entry(ue_sk, &uevent_sock_list, list) { | ||
| 256 | struct sock *uevent_sock = ue_sk->sk; | ||
| 215 | struct sk_buff *skb; | 257 | struct sk_buff *skb; |
| 216 | size_t len; | 258 | size_t len; |
| 217 | 259 | ||
| @@ -233,18 +275,21 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 233 | } | 275 | } |
| 234 | 276 | ||
| 235 | NETLINK_CB(skb).dst_group = 1; | 277 | NETLINK_CB(skb).dst_group = 1; |
| 236 | retval = netlink_broadcast(uevent_sock, skb, 0, 1, | 278 | retval = netlink_broadcast_filtered(uevent_sock, skb, |
| 237 | GFP_KERNEL); | 279 | 0, 1, GFP_KERNEL, |
| 280 | kobj_bcast_filter, | ||
| 281 | kobj); | ||
| 238 | /* ENOBUFS should be handled in userspace */ | 282 | /* ENOBUFS should be handled in userspace */ |
| 239 | if (retval == -ENOBUFS) | 283 | if (retval == -ENOBUFS) |
| 240 | retval = 0; | 284 | retval = 0; |
| 241 | } else | 285 | } else |
| 242 | retval = -ENOMEM; | 286 | retval = -ENOMEM; |
| 243 | } | 287 | } |
| 288 | mutex_unlock(&uevent_sock_mutex); | ||
| 244 | #endif | 289 | #endif |
| 245 | 290 | ||
| 246 | /* call uevent_helper, usually only enabled during early boot */ | 291 | /* call uevent_helper, usually only enabled during early boot */ |
| 247 | if (uevent_helper[0]) { | 292 | if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { |
| 248 | char *argv [3]; | 293 | char *argv [3]; |
| 249 | 294 | ||
| 250 | argv [0] = uevent_helper; | 295 | argv [0] = uevent_helper; |
| @@ -320,18 +365,58 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) | |||
| 320 | EXPORT_SYMBOL_GPL(add_uevent_var); | 365 | EXPORT_SYMBOL_GPL(add_uevent_var); |
| 321 | 366 | ||
| 322 | #if defined(CONFIG_NET) | 367 | #if defined(CONFIG_NET) |
| 323 | static int __init kobject_uevent_init(void) | 368 | static int uevent_net_init(struct net *net) |
| 324 | { | 369 | { |
| 325 | uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, | 370 | struct uevent_sock *ue_sk; |
| 326 | 1, NULL, NULL, THIS_MODULE); | 371 | |
| 327 | if (!uevent_sock) { | 372 | ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL); |
| 373 | if (!ue_sk) | ||
| 374 | return -ENOMEM; | ||
| 375 | |||
| 376 | ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, | ||
| 377 | 1, NULL, NULL, THIS_MODULE); | ||
| 378 | if (!ue_sk->sk) { | ||
| 328 | printk(KERN_ERR | 379 | printk(KERN_ERR |
| 329 | "kobject_uevent: unable to create netlink socket!\n"); | 380 | "kobject_uevent: unable to create netlink socket!\n"); |
| 330 | return -ENODEV; | 381 | return -ENODEV; |
| 331 | } | 382 | } |
| 332 | netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); | 383 | mutex_lock(&uevent_sock_mutex); |
| 384 | list_add_tail(&ue_sk->list, &uevent_sock_list); | ||
| 385 | mutex_unlock(&uevent_sock_mutex); | ||
| 333 | return 0; | 386 | return 0; |
| 334 | } | 387 | } |
| 335 | 388 | ||
| 389 | static void uevent_net_exit(struct net *net) | ||
| 390 | { | ||
| 391 | struct uevent_sock *ue_sk; | ||
| 392 | |||
| 393 | mutex_lock(&uevent_sock_mutex); | ||
| 394 | list_for_each_entry(ue_sk, &uevent_sock_list, list) { | ||
| 395 | if (sock_net(ue_sk->sk) == net) | ||
| 396 | goto found; | ||
| 397 | } | ||
| 398 | mutex_unlock(&uevent_sock_mutex); | ||
| 399 | return; | ||
| 400 | |||
| 401 | found: | ||
| 402 | list_del(&ue_sk->list); | ||
| 403 | mutex_unlock(&uevent_sock_mutex); | ||
| 404 | |||
| 405 | netlink_kernel_release(ue_sk->sk); | ||
| 406 | kfree(ue_sk); | ||
| 407 | } | ||
| 408 | |||
| 409 | static struct pernet_operations uevent_net_ops = { | ||
| 410 | .init = uevent_net_init, | ||
| 411 | .exit = uevent_net_exit, | ||
| 412 | }; | ||
| 413 | |||
| 414 | static int __init kobject_uevent_init(void) | ||
| 415 | { | ||
| 416 | netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); | ||
| 417 | return register_pernet_subsys(&uevent_net_ops); | ||
| 418 | } | ||
| 419 | |||
| 420 | |||
| 336 | postcore_initcall(kobject_uevent_init); | 421 | postcore_initcall(kobject_uevent_init); |
| 337 | #endif | 422 | #endif |
diff --git a/lib/kref.c b/lib/kref.c index 6d19f690380b..d3d227a08a4b 100644 --- a/lib/kref.c +++ b/lib/kref.c | |||
| @@ -16,23 +16,13 @@ | |||
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | * kref_set - initialize object and set refcount to requested number. | ||
| 20 | * @kref: object in question. | ||
| 21 | * @num: initial reference counter | ||
| 22 | */ | ||
| 23 | void kref_set(struct kref *kref, int num) | ||
| 24 | { | ||
| 25 | atomic_set(&kref->refcount, num); | ||
| 26 | smp_mb(); | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * kref_init - initialize object. | 19 | * kref_init - initialize object. |
| 31 | * @kref: object in question. | 20 | * @kref: object in question. |
| 32 | */ | 21 | */ |
| 33 | void kref_init(struct kref *kref) | 22 | void kref_init(struct kref *kref) |
| 34 | { | 23 | { |
| 35 | kref_set(kref, 1); | 24 | atomic_set(&kref->refcount, 1); |
| 25 | smp_mb(); | ||
| 36 | } | 26 | } |
| 37 | 27 | ||
| 38 | /** | 28 | /** |
| @@ -72,7 +62,6 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref)) | |||
| 72 | return 0; | 62 | return 0; |
| 73 | } | 63 | } |
| 74 | 64 | ||
| 75 | EXPORT_SYMBOL(kref_set); | ||
| 76 | EXPORT_SYMBOL(kref_init); | 65 | EXPORT_SYMBOL(kref_init); |
| 77 | EXPORT_SYMBOL(kref_get); | 66 | EXPORT_SYMBOL(kref_get); |
| 78 | EXPORT_SYMBOL(kref_put); | 67 | EXPORT_SYMBOL(kref_put); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 46d34b0b74a8..b8a2f549ab0e 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -267,7 +267,8 @@ int strict_strtoll(const char *cp, unsigned int base, long long *res) | |||
| 267 | } | 267 | } |
| 268 | EXPORT_SYMBOL(strict_strtoll); | 268 | EXPORT_SYMBOL(strict_strtoll); |
| 269 | 269 | ||
| 270 | static int skip_atoi(const char **s) | 270 | static noinline_for_stack |
| 271 | int skip_atoi(const char **s) | ||
| 271 | { | 272 | { |
| 272 | int i = 0; | 273 | int i = 0; |
| 273 | 274 | ||
| @@ -287,7 +288,8 @@ static int skip_atoi(const char **s) | |||
| 287 | /* Formats correctly any integer in [0,99999]. | 288 | /* Formats correctly any integer in [0,99999]. |
| 288 | * Outputs from one to five digits depending on input. | 289 | * Outputs from one to five digits depending on input. |
| 289 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ | 290 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ |
| 290 | static char *put_dec_trunc(char *buf, unsigned q) | 291 | static noinline_for_stack |
| 292 | char *put_dec_trunc(char *buf, unsigned q) | ||
| 291 | { | 293 | { |
| 292 | unsigned d3, d2, d1, d0; | 294 | unsigned d3, d2, d1, d0; |
| 293 | d1 = (q>>4) & 0xf; | 295 | d1 = (q>>4) & 0xf; |
| @@ -324,7 +326,8 @@ static char *put_dec_trunc(char *buf, unsigned q) | |||
| 324 | return buf; | 326 | return buf; |
| 325 | } | 327 | } |
| 326 | /* Same with if's removed. Always emits five digits */ | 328 | /* Same with if's removed. Always emits five digits */ |
| 327 | static char *put_dec_full(char *buf, unsigned q) | 329 | static noinline_for_stack |
| 330 | char *put_dec_full(char *buf, unsigned q) | ||
| 328 | { | 331 | { |
| 329 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ | 332 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ |
| 330 | /* but anyway, gcc produces better code with full-sized ints */ | 333 | /* but anyway, gcc produces better code with full-sized ints */ |
| @@ -366,7 +369,8 @@ static char *put_dec_full(char *buf, unsigned q) | |||
| 366 | return buf; | 369 | return buf; |
| 367 | } | 370 | } |
| 368 | /* No inlining helps gcc to use registers better */ | 371 | /* No inlining helps gcc to use registers better */ |
| 369 | static noinline char *put_dec(char *buf, unsigned long long num) | 372 | static noinline_for_stack |
| 373 | char *put_dec(char *buf, unsigned long long num) | ||
| 370 | { | 374 | { |
| 371 | while (1) { | 375 | while (1) { |
| 372 | unsigned rem; | 376 | unsigned rem; |
| @@ -417,8 +421,9 @@ struct printf_spec { | |||
| 417 | s16 precision; /* # of digits/chars */ | 421 | s16 precision; /* # of digits/chars */ |
| 418 | }; | 422 | }; |
| 419 | 423 | ||
| 420 | static char *number(char *buf, char *end, unsigned long long num, | 424 | static noinline_for_stack |
| 421 | struct printf_spec spec) | 425 | char *number(char *buf, char *end, unsigned long long num, |
| 426 | struct printf_spec spec) | ||
| 422 | { | 427 | { |
| 423 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ | 428 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ |
| 424 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ | 429 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ |
| @@ -537,7 +542,8 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 537 | return buf; | 542 | return buf; |
| 538 | } | 543 | } |
| 539 | 544 | ||
| 540 | static char *string(char *buf, char *end, const char *s, struct printf_spec spec) | 545 | static noinline_for_stack |
| 546 | char *string(char *buf, char *end, const char *s, struct printf_spec spec) | ||
| 541 | { | 547 | { |
| 542 | int len, i; | 548 | int len, i; |
| 543 | 549 | ||
| @@ -567,8 +573,9 @@ static char *string(char *buf, char *end, const char *s, struct printf_spec spec | |||
| 567 | return buf; | 573 | return buf; |
| 568 | } | 574 | } |
| 569 | 575 | ||
| 570 | static char *symbol_string(char *buf, char *end, void *ptr, | 576 | static noinline_for_stack |
| 571 | struct printf_spec spec, char ext) | 577 | char *symbol_string(char *buf, char *end, void *ptr, |
| 578 | struct printf_spec spec, char ext) | ||
| 572 | { | 579 | { |
| 573 | unsigned long value = (unsigned long) ptr; | 580 | unsigned long value = (unsigned long) ptr; |
| 574 | #ifdef CONFIG_KALLSYMS | 581 | #ifdef CONFIG_KALLSYMS |
| @@ -588,8 +595,9 @@ static char *symbol_string(char *buf, char *end, void *ptr, | |||
| 588 | #endif | 595 | #endif |
| 589 | } | 596 | } |
| 590 | 597 | ||
| 591 | static char *resource_string(char *buf, char *end, struct resource *res, | 598 | static noinline_for_stack |
| 592 | struct printf_spec spec, const char *fmt) | 599 | char *resource_string(char *buf, char *end, struct resource *res, |
| 600 | struct printf_spec spec, const char *fmt) | ||
| 593 | { | 601 | { |
| 594 | #ifndef IO_RSRC_PRINTK_SIZE | 602 | #ifndef IO_RSRC_PRINTK_SIZE |
| 595 | #define IO_RSRC_PRINTK_SIZE 6 | 603 | #define IO_RSRC_PRINTK_SIZE 6 |
| @@ -690,8 +698,9 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
| 690 | return string(buf, end, sym, spec); | 698 | return string(buf, end, sym, spec); |
| 691 | } | 699 | } |
| 692 | 700 | ||
| 693 | static char *mac_address_string(char *buf, char *end, u8 *addr, | 701 | static noinline_for_stack |
| 694 | struct printf_spec spec, const char *fmt) | 702 | char *mac_address_string(char *buf, char *end, u8 *addr, |
| 703 | struct printf_spec spec, const char *fmt) | ||
| 695 | { | 704 | { |
| 696 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; | 705 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; |
| 697 | char *p = mac_addr; | 706 | char *p = mac_addr; |
| @@ -714,7 +723,8 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, | |||
| 714 | return string(buf, end, mac_addr, spec); | 723 | return string(buf, end, mac_addr, spec); |
| 715 | } | 724 | } |
| 716 | 725 | ||
| 717 | static char *ip4_string(char *p, const u8 *addr, const char *fmt) | 726 | static noinline_for_stack |
| 727 | char *ip4_string(char *p, const u8 *addr, const char *fmt) | ||
| 718 | { | 728 | { |
| 719 | int i; | 729 | int i; |
| 720 | bool leading_zeros = (fmt[0] == 'i'); | 730 | bool leading_zeros = (fmt[0] == 'i'); |
| @@ -763,7 +773,8 @@ static char *ip4_string(char *p, const u8 *addr, const char *fmt) | |||
| 763 | return p; | 773 | return p; |
| 764 | } | 774 | } |
| 765 | 775 | ||
| 766 | static char *ip6_compressed_string(char *p, const char *addr) | 776 | static noinline_for_stack |
| 777 | char *ip6_compressed_string(char *p, const char *addr) | ||
| 767 | { | 778 | { |
| 768 | int i, j, range; | 779 | int i, j, range; |
| 769 | unsigned char zerolength[8]; | 780 | unsigned char zerolength[8]; |
| @@ -843,7 +854,8 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
| 843 | return p; | 854 | return p; |
| 844 | } | 855 | } |
| 845 | 856 | ||
| 846 | static char *ip6_string(char *p, const char *addr, const char *fmt) | 857 | static noinline_for_stack |
| 858 | char *ip6_string(char *p, const char *addr, const char *fmt) | ||
| 847 | { | 859 | { |
| 848 | int i; | 860 | int i; |
| 849 | 861 | ||
| @@ -858,8 +870,9 @@ static char *ip6_string(char *p, const char *addr, const char *fmt) | |||
| 858 | return p; | 870 | return p; |
| 859 | } | 871 | } |
| 860 | 872 | ||
| 861 | static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | 873 | static noinline_for_stack |
| 862 | struct printf_spec spec, const char *fmt) | 874 | char *ip6_addr_string(char *buf, char *end, const u8 *addr, |
| 875 | struct printf_spec spec, const char *fmt) | ||
| 863 | { | 876 | { |
| 864 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; | 877 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; |
| 865 | 878 | ||
| @@ -871,8 +884,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
| 871 | return string(buf, end, ip6_addr, spec); | 884 | return string(buf, end, ip6_addr, spec); |
| 872 | } | 885 | } |
| 873 | 886 | ||
| 874 | static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | 887 | static noinline_for_stack |
| 875 | struct printf_spec spec, const char *fmt) | 888 | char *ip4_addr_string(char *buf, char *end, const u8 *addr, |
| 889 | struct printf_spec spec, const char *fmt) | ||
| 876 | { | 890 | { |
| 877 | char ip4_addr[sizeof("255.255.255.255")]; | 891 | char ip4_addr[sizeof("255.255.255.255")]; |
| 878 | 892 | ||
| @@ -881,8 +895,9 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
| 881 | return string(buf, end, ip4_addr, spec); | 895 | return string(buf, end, ip4_addr, spec); |
| 882 | } | 896 | } |
| 883 | 897 | ||
| 884 | static char *uuid_string(char *buf, char *end, const u8 *addr, | 898 | static noinline_for_stack |
| 885 | struct printf_spec spec, const char *fmt) | 899 | char *uuid_string(char *buf, char *end, const u8 *addr, |
| 900 | struct printf_spec spec, const char *fmt) | ||
| 886 | { | 901 | { |
| 887 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; | 902 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; |
| 888 | char *p = uuid; | 903 | char *p = uuid; |
| @@ -970,8 +985,9 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
| 970 | * function pointers are really function descriptors, which contain a | 985 | * function pointers are really function descriptors, which contain a |
| 971 | * pointer to the real address. | 986 | * pointer to the real address. |
| 972 | */ | 987 | */ |
| 973 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 988 | static noinline_for_stack |
| 974 | struct printf_spec spec) | 989 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
| 990 | struct printf_spec spec) | ||
| 975 | { | 991 | { |
| 976 | if (!ptr) | 992 | if (!ptr) |
| 977 | return string(buf, end, "(null)", spec); | 993 | return string(buf, end, "(null)", spec); |
| @@ -1040,7 +1056,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1040 | * @precision: precision of a number | 1056 | * @precision: precision of a number |
| 1041 | * @qualifier: qualifier of a number (long, size_t, ...) | 1057 | * @qualifier: qualifier of a number (long, size_t, ...) |
| 1042 | */ | 1058 | */ |
| 1043 | static int format_decode(const char *fmt, struct printf_spec *spec) | 1059 | static noinline_for_stack |
| 1060 | int format_decode(const char *fmt, struct printf_spec *spec) | ||
| 1044 | { | 1061 | { |
| 1045 | const char *start = fmt; | 1062 | const char *start = fmt; |
| 1046 | 1063 | ||
| @@ -1980,7 +1997,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
| 1980 | { | 1997 | { |
| 1981 | char *s = (char *)va_arg(args, char *); | 1998 | char *s = (char *)va_arg(args, char *); |
| 1982 | if (field_width == -1) | 1999 | if (field_width == -1) |
| 1983 | field_width = SHORT_MAX; | 2000 | field_width = SHRT_MAX; |
| 1984 | /* first, skip leading white space in buffer */ | 2001 | /* first, skip leading white space in buffer */ |
| 1985 | str = skip_spaces(str); | 2002 | str = skip_spaces(str); |
| 1986 | 2003 | ||
