Stop polluting sysctl, move to debugfs for SCHED_DEBUG stuff.
Showing the changes to kernel (3 of 3 files). Show all
Unified · Split
| @@ -299,6 +299,10 @@ static __init int sched_init_debug(void) · 298 unmodified lines | ||
| 299 | 299 | debugfs_create_file("tunable_scaling", 0644, debugfs_sched, NULL, &sched_scaling_fops); |
| 300 | 300 | debugfs_create_u32("migration_cost_ns", 0644, debugfs_sched, &sysctl_sched_migration_cost); |
| 301 | 301 | debugfs_create_u32("nr_migrate", 0644, debugfs_sched, &sysctl_sched_nr_migrate); |
| 302 | + | |
| 303 | + mutex_lock(&sched_domains_mutex); | |
| 304 | + update_sched_domain_debugfs(); | |
| 305 | + mutex_unlock(&sched_domains_mutex); | |
| 302 | 306 | #endif |
| 303 | 307 | |
| 304 | 308 | #ifdef CONFIG_NUMA_BALANCING |
| @@ -316,229 +320,88 @@ late_initcall(sched_init_debug); · 11 unmodified lines | ||
| 316 | 320 | |
| 317 | 321 | #ifdef CONFIG_SMP |
| 318 | 322 | |
| 319 | −#ifdef CONFIG_SYSCTL | |
| 320 | − | |
| 321 | −static struct ctl_table sd_ctl_dir[] = { | |
| 322 | − { | |
| 323 | − .procname = "sched_domain", | |
| 324 | − .mode = 0555, | |
| 325 | − }, | |
| 326 | − {} | |
| 327 | −}; | |
| 328 | − | |
| 329 | −static struct ctl_table sd_ctl_root[] = { | |
| 330 | − { | |
| 331 | − .procname = "kernel", | |
| 332 | − .mode = 0555, | |
| 333 | − .child = sd_ctl_dir, | |
| 334 | − }, | |
| 335 | − {} | |
| 336 | −}; | |
| 337 | − | |
| 338 | −static struct ctl_table *sd_alloc_ctl_entry(int n) | |
| 339 | −{ | |
| 340 | − struct ctl_table *entry = | |
| 341 | − kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL); | |
| 342 | − | |
| 343 | − return entry; | |
| 344 | −} | |
| 345 | − | |
| 346 | −static void sd_free_ctl_entry(struct ctl_table **tablep) | |
| 347 | −{ | |
| 348 | − struct ctl_table *entry; | |
| 349 | − | |
| 350 | − /* | |
| 351 | − * In the intermediate directories, both the child directory and | |
| 352 | − * procname are dynamically allocated and could fail but the mode | |
| 353 | − * will always be set. In the lowest directory the names are | |
| 354 | − * static strings and all have proc handlers. | |
| 355 | − */ | |
| 356 | − for (entry = *tablep; entry->mode; entry++) { | |
| 357 | − if (entry->child) | |
| 358 | − sd_free_ctl_entry(&entry->child); | |
| 359 | − if (entry->proc_handler == NULL) | |
| 360 | − kfree(entry->procname); | |
| 361 | − } | |
| 362 | − | |
| 363 | − kfree(*tablep); | |
| 364 | − *tablep = NULL; | |
| 365 | −} | |
| 366 | − | |
| 367 | −static void | |
| 368 | −set_table_entry(struct ctl_table *entry, | |
| 369 | − const char *procname, void *data, int maxlen, | |
| 370 | − umode_t mode, proc_handler *proc_handler) | |
| 371 | −{ | |
| 372 | − entry->procname = procname; | |
| 373 | − entry->data = data; | |
| 374 | − entry->maxlen = maxlen; | |
| 375 | − entry->mode = mode; | |
| 376 | − entry->proc_handler = proc_handler; | |
| 377 | −} | |
| 323 | +static cpumask_var_t sd_sysctl_cpus; | |
| 324 | +static struct dentry *sd_dentry; | |
| 378 | 325 | |
| 379 | −static int sd_ctl_doflags(struct ctl_table *table, int write, | |
| 380 | − void *buffer, size_t *lenp, loff_t *ppos) | |
| 326 | +static int sd_flags_show(struct seq_file *m, void *v) | |
| 381 | 327 | { |
| 382 | − unsigned long flags = *(unsigned long *)table->data; | |
| 383 | − size_t data_size = 0; | |
| 384 | − size_t len = 0; | |
| 385 | − char *tmp, *buf; | |
| 328 | + unsigned long flags = *(unsigned int *)m->private; | |
| 386 | 329 | int idx; |
| 387 | 330 | |
| 388 | − if (write) | |
| 389 | − return 0; | |
| 390 | − | |
| 391 | − for_each_set_bit(idx, &flags, __SD_FLAG_CNT) { | |
| 392 | − char *name = sd_flag_debug[idx].name; | |
| 393 | − | |
| 394 | − /* Name plus whitespace */ | |
| 395 | − data_size += strlen(name) + 1; | |
| 396 | − } | |
| 397 | − | |
| 398 | − if (*ppos > data_size) { | |
| 399 | − *lenp = 0; | |
| 400 | − return 0; | |
| 401 | − } | |
| 402 | − | |
| 403 | − buf = kcalloc(data_size + 1, sizeof(*buf), GFP_KERNEL); | |
| 404 | − if (!buf) | |
| 405 | − return -ENOMEM; | |
| 406 | − | |
| 407 | 331 | for_each_set_bit(idx, &flags, __SD_FLAG_CNT) { |
| 408 | − char *name = sd_flag_debug[idx].name; | |
| 409 | − | |
| 410 | − len += snprintf(buf + len, strlen(name) + 2, "%s ", name); | |
| 411 | − } | |
| 412 | − | |
| 413 | − tmp = buf + *ppos; | |
| 414 | − len -= *ppos; | |
| 415 | − | |
| 416 | − if (len > *lenp) | |
| 417 | − len = *lenp; | |
| 418 | − if (len) | |
| 419 | − memcpy(buffer, tmp, len); | |
| 420 | − if (len < *lenp) { | |
| 421 | − ((char *)buffer)[len] = '\n'; | |
| 422 | − len++; | |
| 332 | + seq_puts(m, sd_flag_debug[idx].name); | |
| 333 | + seq_puts(m, " "); | |
| 423 | 334 | } |
| 424 | − | |
| 425 | − *lenp = len; | |
| 426 | − *ppos += len; | |
| 427 | − | |
| 428 | − kfree(buf); | |
| 335 | + seq_puts(m, "\n"); | |
| 429 | 336 | |
| 430 | 337 | return 0; |
| 431 | 338 | } |
| 432 | 339 | |
| 433 | −static struct ctl_table * | |
| 434 | −sd_alloc_ctl_domain_table(struct sched_domain *sd) | |
| 435 | −{ | |
| 436 | − struct ctl_table *table = sd_alloc_ctl_entry(9); | |
| 437 | − | |
| 438 | − if (table == NULL) | |
| 439 | − return NULL; | |
| 440 | − | |
| 441 | − set_table_entry(&table[0], "min_interval", &sd->min_interval, sizeof(long), 0644, proc_doulongvec_minmax); | |
| 442 | − set_table_entry(&table[1], "max_interval", &sd->max_interval, sizeof(long), 0644, proc_doulongvec_minmax); | |
| 443 | − set_table_entry(&table[2], "busy_factor", &sd->busy_factor, sizeof(int), 0644, proc_dointvec_minmax); | |
| 444 | − set_table_entry(&table[3], "imbalance_pct", &sd->imbalance_pct, sizeof(int), 0644, proc_dointvec_minmax); | |
| 445 | − set_table_entry(&table[4], "cache_nice_tries", &sd->cache_nice_tries, sizeof(int), 0644, proc_dointvec_minmax); | |
| 446 | − set_table_entry(&table[5], "flags", &sd->flags, sizeof(int), 0444, sd_ctl_doflags); | |
| 447 | − set_table_entry(&table[6], "max_newidle_lb_cost", &sd->max_newidle_lb_cost, sizeof(long), 0644, proc_doulongvec_minmax); | |
| 448 | − set_table_entry(&table[7], "name", sd->name, CORENAME_MAX_SIZE, 0444, proc_dostring); | |
| 449 | − /* &table[8] is terminator */ | |
| 450 | − | |
| 451 | − return table; | |
| 452 | −} | |
| 453 | − | |
| 454 | −static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu) | |
| 340 | +static int sd_flags_open(struct inode *inode, struct file *file) | |
| 455 | 341 | { |
| 456 | − struct ctl_table *entry, *table; | |
| 457 | − struct sched_domain *sd; | |
| 458 | − int domain_num = 0, i; | |
| 459 | − char buf[32]; | |
| 460 | − | |
| 461 | − for_each_domain(cpu, sd) | |
| 462 | − domain_num++; | |
| 463 | − entry = table = sd_alloc_ctl_entry(domain_num + 1); | |
| 464 | − if (table == NULL) | |
| 465 | − return NULL; | |
| 466 | − | |
| 467 | − i = 0; | |
| 468 | − for_each_domain(cpu, sd) { | |
| 469 | − snprintf(buf, 32, "domain%d", i); | |
| 470 | − entry->procname = kstrdup(buf, GFP_KERNEL); | |
| 471 | − entry->mode = 0555; | |
| 472 | − entry->child = sd_alloc_ctl_domain_table(sd); | |
| 473 | − entry++; | |
| 474 | − i++; | |
| 475 | − } | |
| 476 | − return table; | |
| 342 | + return single_open(file, sd_flags_show, inode->i_private); | |
| 477 | 343 | } |
| 478 | 344 | |
| 479 | −static cpumask_var_t sd_sysctl_cpus; | |
| 480 | −static struct ctl_table_header *sd_sysctl_header; | |
| 345 | +static const struct file_operations sd_flags_fops = { | |
| 346 | + .open = sd_flags_open, | |
| 347 | + .read = seq_read, | |
| 348 | + .llseek = seq_lseek, | |
| 349 | + .release = single_release, | |
| 350 | +}; | |
| 481 | 351 | |
| 482 | −void register_sched_domain_sysctl(void) | |
| 352 | +static void register_sd(struct sched_domain *sd, struct dentry *parent) | |
| 483 | 353 | { |
| 484 | − static struct ctl_table *cpu_entries; | |
| 485 | − static struct ctl_table **cpu_idx; | |
| 486 | − static bool init_done = false; | |
| 487 | − char buf[32]; | |
| 488 | − int i; | |
| 354 | +#define SDM(type, mode, member) \ | |
| 355 | + debugfs_create_##type(#member, mode, parent, &sd->member) | |
| 489 | 356 | |
| 490 | − if (!cpu_entries) { | |
| 491 | − cpu_entries = sd_alloc_ctl_entry(num_possible_cpus() + 1); | |
| 492 | − if (!cpu_entries) | |
| 493 | − return; | |
| 494 | − | |
| 495 | − WARN_ON(sd_ctl_dir[0].child); | |
| 496 | − sd_ctl_dir[0].child = cpu_entries; | |
| 497 | − } | |
| 357 | + SDM(ulong, 0644, min_interval); | |
| 358 | + SDM(ulong, 0644, max_interval); | |
| 359 | + SDM(u64, 0644, max_newidle_lb_cost); | |
| 360 | + SDM(u32, 0644, busy_factor); | |
| 361 | + SDM(u32, 0644, imbalance_pct); | |
| 362 | + SDM(u32, 0644, cache_nice_tries); | |
| 363 | + SDM(str, 0444, name); | |
| 498 | 364 | |
| 499 | − if (!cpu_idx) { | |
| 500 | − struct ctl_table *e = cpu_entries; | |
| 365 | +#undef SDM | |
| 501 | 366 | |
| 502 | − cpu_idx = kcalloc(nr_cpu_ids, sizeof(struct ctl_table*), GFP_KERNEL); | |
| 503 | − if (!cpu_idx) | |
| 504 | − return; | |
| 367 | + debugfs_create_file("flags", 0444, parent, &sd->flags, &sd_flags_fops); | |
| 368 | +} | |
| 505 | 369 | |
| 506 | − /* deal with sparse possible map */ | |
| 507 | − for_each_possible_cpu(i) { | |
| 508 | − cpu_idx[i] = e; | |
| 509 | − e++; | |
| 510 | − } | |
| 511 | − } | |
| 370 | +void update_sched_domain_debugfs(void) | |
| 371 | +{ | |
| 372 | + int cpu, i; | |
| 512 | 373 | |
| 513 | 374 | if (!cpumask_available(sd_sysctl_cpus)) { |
| 514 | 375 | if (!alloc_cpumask_var(&sd_sysctl_cpus, GFP_KERNEL)) |
| 515 | 376 | return; |
| 516 | − } | |
| 517 | − | |
| 518 | − if (!init_done) { | |
| 519 | − init_done = true; | |
| 520 | − /* init to possible to not have holes in @cpu_entries */ | |
| 521 | 377 | cpumask_copy(sd_sysctl_cpus, cpu_possible_mask); |
| 522 | 378 | } |
| 523 | 379 | |
| 524 | − for_each_cpu(i, sd_sysctl_cpus) { | |
| 525 | − struct ctl_table *e = cpu_idx[i]; | |
| 380 | + if (!sd_dentry) | |
| 381 | + sd_dentry = debugfs_create_dir("domains", debugfs_sched); | |
| 382 | + | |
| 383 | + for_each_cpu(cpu, sd_sysctl_cpus) { | |
| 384 | + struct sched_domain *sd; | |
| 385 | + struct dentry *d_cpu; | |
| 386 | + char buf[32]; | |
| 387 | + | |
| 388 | + snprintf(buf, sizeof(buf), "cpu%d", cpu); | |
| 389 | + debugfs_remove(debugfs_lookup(buf, sd_dentry)); | |
| 390 | + d_cpu = debugfs_create_dir(buf, sd_dentry); | |
| 526 | 391 | |
| 527 | − if (e->child) | |
| 528 | − sd_free_ctl_entry(&e->child); | |
| 392 | + i = 0; | |
| 393 | + for_each_domain(cpu, sd) { | |
| 394 | + struct dentry *d_sd; | |
| 529 | 395 | |
| 530 | − if (!e->procname) { | |
| 531 | − snprintf(buf, 32, "cpu%d", i); | |
| 532 | − e->procname = kstrdup(buf, GFP_KERNEL); | |
| 396 | + snprintf(buf, sizeof(buf), "domain%d", i); | |
| 397 | + d_sd = debugfs_create_dir(buf, d_cpu); | |
| 398 | + | |
| 399 | + register_sd(sd, d_sd); | |
| 400 | + i++; | |
| 533 | 401 | } |
| 534 | − e->mode = 0555; | |
| 535 | − e->child = sd_alloc_ctl_cpu_table(i); | |
| 536 | 402 | |
| 537 | − __cpumask_clear_cpu(i, sd_sysctl_cpus); | |
| 403 | + __cpumask_clear_cpu(cpu, sd_sysctl_cpus); | |
| 538 | 404 | } |
| 539 | − | |
| 540 | − WARN_ON(sd_sysctl_header); | |
| 541 | − sd_sysctl_header = register_sysctl_table(sd_ctl_root); | |
| 542 | 405 | } |
| 543 | 406 | |
| 544 | 407 | void dirty_sched_domain_sysctl(int cpu) |
| @@ -547,13 +410,6 @@ void dirty_sched_domain_sysctl(int cpu) · 2 unmodified lines | ||
| 547 | 410 | __cpumask_set_cpu(cpu, sd_sysctl_cpus); |
| 548 | 411 | } |
| 549 | 412 | |
| 550 | −/* may be called multiple times per register */ | |
| 551 | −void unregister_sched_domain_sysctl(void) | |
| 552 | −{ | |
| 553 | − unregister_sysctl_table(sd_sysctl_header); | |
| 554 | − sd_sysctl_header = NULL; | |
| 555 | −} | |
| 556 | −#endif /* CONFIG_SYSCTL */ | |
| 557 | 413 | #endif /* CONFIG_SMP */ |
| 558 | 414 | |
| 559 | 415 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| @@ -1552,20 +1552,16 @@ static inline unsigned int group_first_cpu(struct sched_group *group) · 1551 unmodified lines | ||
| 1552 | 1552 | |
| 1553 | 1553 | extern int group_balance_cpu(struct sched_group *sg); |
| 1554 | 1554 | |
| 1555 | −#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) | |
| 1556 | −void register_sched_domain_sysctl(void); | |
| 1555 | +#ifdef CONFIG_SCHED_DEBUG | |
| 1556 | +void update_sched_domain_debugfs(void); | |
| 1557 | 1557 | void dirty_sched_domain_sysctl(int cpu); |
| 1558 | −void unregister_sched_domain_sysctl(void); | |
| 1559 | 1558 | #else |
| 1560 | −static inline void register_sched_domain_sysctl(void) | |
| 1559 | +static inline void update_sched_domain_debugfs(void) | |
| 1561 | 1560 | { |
| 1562 | 1561 | } |
| 1563 | 1562 | static inline void dirty_sched_domain_sysctl(int cpu) |
| 1564 | 1563 | { |
| 1565 | 1564 | } |
| 1566 | −static inline void unregister_sched_domain_sysctl(void) | |
| 1567 | −{ | |
| 1568 | −} | |
| 1569 | 1565 | #endif |
| 1570 | 1566 | |
| 1571 | 1567 | extern int sched_update_scaling(void); |
| @@ -2223,7 +2223,6 @@ int sched_init_domains(const struct cpumask *cpu_map) · 2222 unmodified lines | ||
| 2223 | 2223 | doms_cur = &fallback_doms; |
| 2224 | 2224 | cpumask_and(doms_cur[0], cpu_map, housekeeping_cpumask(HK_FLAG_DOMAIN)); |
| 2225 | 2225 | err = build_sched_domains(doms_cur[0], NULL); |
| 2226 | − register_sched_domain_sysctl(); | |
| 2227 | 2226 | |
| 2228 | 2227 | return err; |
| 2229 | 2228 | } |
| @@ -2298,9 +2297,6 @@ void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], · 68 unmodified lines | ||
| 2298 | 2297 | |
| 2299 | 2298 | lockdep_assert_held(&sched_domains_mutex); |
| 2300 | 2299 | |
| 2301 | − /* Always unregister in case we don't destroy any domains: */ | |
| 2302 | − unregister_sched_domain_sysctl(); | |
| 2303 | − | |
| 2304 | 2300 | /* Let the architecture update CPU core mappings: */ |
| 2305 | 2301 | new_topology = arch_update_cpu_topology(); |
| 2306 | 2302 | |
| @@ -2389,7 +2385,7 @@ match3: · 82 unmodified lines | ||
| 2389 | 2385 | dattr_cur = dattr_new; |
| 2390 | 2386 | ndoms_cur = ndoms_new; |
| 2391 | 2387 | |
| 2392 | − register_sched_domain_sysctl(); | |
| 2388 | + update_sched_domain_debugfs(); | |
| 2393 | 2389 | } |
| 2394 | 2390 | |
| 2395 | 2391 | /* |