+ if (token[j] == 0)
+ break;
+
+ if (str[j] == token[j])
+ continue;
+
+ if (str[j] < 'A' || 'Z' < str[j])
+ break;
+
+ if (str[j] - 'A' + 'a' != token[j])
+ break;
+ }
+ }
+
+ return -EINVAL; /* no match */
+}
+
+int
+libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
+{
+ int m = 0;
+ char op = 0;
+ int matched;
+ int n;
+ int t;
+
+ /* Allow a number for backwards compatibility */
+
+ for (n = strlen(str); n > 0; n--)
+ if (!isspace(str[n-1]))
+ break;
+ matched = n;
+
+ if ((t = sscanf(str, "%i%n", &m, &matched)) >= 1 &&
+ matched == n) {
+ *mask = m;
+ return 0;
+ }
+
+ /* <str> must be a list of debug tokens or numbers separated by
+ * whitespace and optionally an operator ('+' or '-'). If an operator
+ * appears first in <str>, '*mask' is used as the starting point
+ * (relative), otherwise 0 is used (absolute). An operator applies to
+ * all following tokens up to the next operator. */
+
+ matched = 0;
+ while (*str != 0) {
+ while (isspace(*str)) /* skip whitespace */
+ str++;
+
+ if (*str == 0)
+ break;
+
+ if (*str == '+' || *str == '-') {
+ op = *str++;
+
+ /* op on first token == relative */
+ if (!matched)
+ m = *mask;
+
+ while (isspace(*str)) /* skip whitespace */
+ str++;
+
+ if (*str == 0) /* trailing op */
+ return -EINVAL;
+ }
+
+ /* find token length */
+ for (n = 0; str[n] != 0 && !isspace(str[n]); n++);
+
+ /* match token */
+ if (libcfs_debug_token2mask(&t, str, n, is_subsys) != 0)
+ return -EINVAL;
+
+ matched = 1;
+ if (op == '-')
+ m &= ~t;
+ else
+ m |= t;
+
+ str += n;
+ }
+
+ if (!matched)
+ return -EINVAL;
+
+ *mask = m;
+ return 0;
+}
+
+void libcfs_debug_dumplog_internal(void *arg)
+{
+ CFS_DECL_JOURNAL_DATA;
+
+ CFS_PUSH_JOURNAL;
+
+ snprintf(debug_file_name, sizeof(debug_file_path) - 1, "%s.%ld.%ld",
+ debug_file_path, cfs_time_current_sec(), (long)arg);