|
32 | 32 | #define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ) |
33 | 33 | #define PARPORT_MIN_SPINTIME_VALUE 1 |
34 | 34 | #define PARPORT_MAX_SPINTIME_VALUE 1000 |
| 35 | +/* |
| 36 | + * PARPORT_BASE_* is the size of the known parts of the sysctl path |
| 37 | + * in dev/partport/%s/devices/%s. "dev/parport/"(12), "/devices/"(9 |
| 38 | + * and null char(1). |
| 39 | + */ |
| 40 | +#define PARPORT_BASE_PATH_SIZE 13 |
| 41 | +#define PARPORT_BASE_DEVICES_PATH_SIZE 22 |
35 | 42 |
|
36 | 43 | static int do_active_device(struct ctl_table *table, int write, |
37 | 44 | void *result, size_t *lenp, loff_t *ppos) |
@@ -260,9 +267,6 @@ struct parport_sysctl_table { |
260 | 267 | struct ctl_table_header *sysctl_header; |
261 | 268 | struct ctl_table vars[12]; |
262 | 269 | struct ctl_table device_dir[2]; |
263 | | - struct ctl_table port_dir[2]; |
264 | | - struct ctl_table parport_dir[2]; |
265 | | - struct ctl_table dev_dir[2]; |
266 | 270 | }; |
267 | 271 |
|
268 | 272 | static const struct parport_sysctl_table parport_sysctl_template = { |
@@ -305,7 +309,6 @@ static const struct parport_sysctl_table parport_sysctl_template = { |
305 | 309 | .mode = 0444, |
306 | 310 | .proc_handler = do_hardware_modes |
307 | 311 | }, |
308 | | - PARPORT_DEVICES_ROOT_DIR, |
309 | 312 | #ifdef CONFIG_PARPORT_1284 |
310 | 313 | { |
311 | 314 | .procname = "autoprobe", |
@@ -355,18 +358,6 @@ static const struct parport_sysctl_table parport_sysctl_template = { |
355 | 358 | }, |
356 | 359 | {} |
357 | 360 | }, |
358 | | - { |
359 | | - PARPORT_PORT_DIR(NULL), |
360 | | - {} |
361 | | - }, |
362 | | - { |
363 | | - PARPORT_PARPORT_DIR(NULL), |
364 | | - {} |
365 | | - }, |
366 | | - { |
367 | | - PARPORT_DEV_DIR(NULL), |
368 | | - {} |
369 | | - } |
370 | 361 | }; |
371 | 362 |
|
372 | 363 | struct parport_device_sysctl_table |
@@ -473,40 +464,78 @@ parport_default_sysctl_table = { |
473 | 464 | } |
474 | 465 | }; |
475 | 466 |
|
476 | | - |
477 | 467 | int parport_proc_register(struct parport *port) |
478 | 468 | { |
479 | 469 | struct parport_sysctl_table *t; |
480 | | - int i; |
| 470 | + struct ctl_table_header *devices_h; |
| 471 | + char *tmp_dir_path; |
| 472 | + size_t tmp_path_len, port_name_len; |
| 473 | + int bytes_written, i, err = 0; |
481 | 474 |
|
482 | 475 | t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL); |
483 | 476 | if (t == NULL) |
484 | 477 | return -ENOMEM; |
485 | 478 |
|
486 | 479 | t->device_dir[0].extra1 = port; |
487 | 480 |
|
488 | | - for (i = 0; i < 5; i++) |
| 481 | + t->vars[0].data = &port->spintime; |
| 482 | + for (i = 0; i < 5; i++) { |
489 | 483 | t->vars[i].extra1 = port; |
| 484 | + t->vars[5 + i].extra2 = &port->probe_info[i]; |
| 485 | + } |
490 | 486 |
|
491 | | - t->vars[0].data = &port->spintime; |
492 | | - t->vars[5].child = t->device_dir; |
493 | | - |
494 | | - for (i = 0; i < 5; i++) |
495 | | - t->vars[6 + i].extra2 = &port->probe_info[i]; |
| 487 | + port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN); |
| 488 | + /* |
| 489 | + * Allocate a buffer for two paths: dev/parport/PORT and dev/parport/PORT/devices. |
| 490 | + * We calculate for the second as that will give us enough for the first. |
| 491 | + */ |
| 492 | + tmp_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len; |
| 493 | + tmp_dir_path = kzalloc(tmp_path_len, GFP_KERNEL); |
| 494 | + if (!tmp_dir_path) { |
| 495 | + err = -ENOMEM; |
| 496 | + goto exit_free_t; |
| 497 | + } |
496 | 498 |
|
497 | | - t->port_dir[0].procname = port->name; |
| 499 | + bytes_written = snprintf(tmp_dir_path, tmp_path_len, |
| 500 | + "dev/parport/%s/devices", port->name); |
| 501 | + if (tmp_path_len <= bytes_written) { |
| 502 | + err = -ENOENT; |
| 503 | + goto exit_free_tmp_dir_path; |
| 504 | + } |
| 505 | + devices_h = register_sysctl(tmp_dir_path, t->device_dir); |
| 506 | + if (devices_h == NULL) { |
| 507 | + err = -ENOENT; |
| 508 | + goto exit_free_tmp_dir_path; |
| 509 | + } |
498 | 510 |
|
499 | | - t->port_dir[0].child = t->vars; |
500 | | - t->parport_dir[0].child = t->port_dir; |
501 | | - t->dev_dir[0].child = t->parport_dir; |
| 511 | + tmp_path_len = PARPORT_BASE_PATH_SIZE + port_name_len; |
| 512 | + bytes_written = snprintf(tmp_dir_path, tmp_path_len, |
| 513 | + "dev/parport/%s", port->name); |
| 514 | + if (tmp_path_len <= bytes_written) { |
| 515 | + err = -ENOENT; |
| 516 | + goto unregister_devices_h; |
| 517 | + } |
502 | 518 |
|
503 | | - t->sysctl_header = register_sysctl_table(t->dev_dir); |
| 519 | + t->sysctl_header = register_sysctl(tmp_dir_path, t->vars); |
504 | 520 | if (t->sysctl_header == NULL) { |
505 | | - kfree(t); |
506 | | - t = NULL; |
| 521 | + err = -ENOENT; |
| 522 | + goto unregister_devices_h; |
507 | 523 | } |
| 524 | + |
508 | 525 | port->sysctl_table = t; |
| 526 | + |
| 527 | + kfree(tmp_dir_path); |
509 | 528 | return 0; |
| 529 | + |
| 530 | +unregister_devices_h: |
| 531 | + unregister_sysctl_table(devices_h); |
| 532 | + |
| 533 | +exit_free_tmp_dir_path: |
| 534 | + kfree(tmp_dir_path); |
| 535 | + |
| 536 | +exit_free_t: |
| 537 | + kfree(t); |
| 538 | + return err; |
510 | 539 | } |
511 | 540 |
|
512 | 541 | int parport_proc_unregister(struct parport *port) |
|
0 commit comments