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

[PATCH] pktcdvd: add sysfs and debugfs interface

Add a sysfs and debugfs interface to the pktcdvd driver.

Look into the Documentation/ABI/testing/* files in the patch for more info.

Signed-off-by: Thomas Maier <balagi@justmail.de>
Signed-off-by: Peter Osterlund <petero2@telia.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Thomas Maier and committed by
Linus Torvalds
32694850 0a0fc960

+583 -5
+20
Documentation/ABI/testing/debugfs-pktcdvd
··· 1 + What: /debug/pktcdvd/pktcdvd[0-7] 2 + Date: Oct. 2006 3 + KernelVersion: 2.6.19 4 + Contact: Thomas Maier <balagi@justmail.de> 5 + Description: 6 + 7 + debugfs interface 8 + ----------------- 9 + 10 + The pktcdvd module (packet writing driver) creates 11 + these files in debugfs: 12 + 13 + /debug/pktcdvd/pktcdvd[0-7]/ 14 + info (0444) Lots of human readable driver 15 + statistics and infos. Multiple lines! 16 + 17 + Example: 18 + ------- 19 + 20 + cat /debug/pktcdvd/pktcdvd0/info
+72
Documentation/ABI/testing/sysfs-class-pktcdvd
··· 1 + What: /sys/class/pktcdvd/ 2 + Date: Oct. 2006 3 + KernelVersion: 2.6.19 4 + Contact: Thomas Maier <balagi@justmail.de> 5 + Description: 6 + 7 + sysfs interface 8 + --------------- 9 + 10 + The pktcdvd module (packet writing driver) creates 11 + these files in the sysfs: 12 + (<devid> is in format major:minor ) 13 + 14 + /sys/class/pktcdvd/ 15 + add (0200) Write a block device id (major:minor) 16 + to create a new pktcdvd device and map 17 + it to the block device. 18 + 19 + remove (0200) Write the pktcdvd device id (major:minor) 20 + to it to remove the pktcdvd device. 21 + 22 + device_map (0444) Shows the device mapping in format: 23 + pktcdvd[0-7] <pktdevid> <blkdevid> 24 + 25 + /sys/class/pktcdvd/pktcdvd[0-7]/ 26 + dev (0444) Device id 27 + uevent (0200) To send an uevent. 28 + 29 + /sys/class/pktcdvd/pktcdvd[0-7]/stat/ 30 + packets_started (0444) Number of started packets. 31 + packets_finished (0444) Number of finished packets. 32 + 33 + kb_written (0444) kBytes written. 34 + kb_read (0444) kBytes read. 35 + kb_read_gather (0444) kBytes read to fill write packets. 36 + 37 + reset (0200) Write any value to it to reset 38 + pktcdvd device statistic values, like 39 + bytes read/written. 40 + 41 + /sys/class/pktcdvd/pktcdvd[0-7]/write_queue/ 42 + size (0444) Contains the size of the bio write 43 + queue. 44 + 45 + congestion_off (0644) If bio write queue size is below 46 + this mark, accept new bio requests 47 + from the block layer. 48 + 49 + congestion_on (0644) If bio write queue size is higher 50 + as this mark, do no longer accept 51 + bio write requests from the block 52 + layer and wait till the pktcdvd 53 + device has processed enough bio's 54 + so that bio write queue size is 55 + below congestion off mark. 56 + A value of <= 0 disables congestion 57 + control. 58 + 59 + 60 + Example: 61 + -------- 62 + To use the pktcdvd sysfs interface directly, you can do: 63 + 64 + # create a new pktcdvd device mapped to /dev/hdc 65 + echo "22:0" >/sys/class/pktcdvd/add 66 + cat /sys/class/pktcdvd/device_map 67 + # assuming device pktcdvd0 was created, look at stat's 68 + cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written 69 + # print the device id of the mapped block device 70 + fgrep pktcdvd0 /sys/class/pktcdvd/device_map 71 + # remove device, using pktcdvd0 device id 253:0 72 + echo "253:0" >/sys/class/pktcdvd/remove
+35
Documentation/cdrom/packet-writing.txt
··· 90 90 to create an ext2 filesystem on the disc. 91 91 92 92 93 + Using the pktcdvd sysfs interface 94 + --------------------------------- 95 + 96 + Since Linux 2.6.19, the pktcdvd module has a sysfs interface 97 + and can be controlled by it. For example the "pktcdvd" tool uses 98 + this interface. (see http://people.freenet.de/BalaGi#pktcdvd ) 99 + 100 + "pktcdvd" works similar to "pktsetup", e.g.: 101 + 102 + # pktcdvd -a dev_name /dev/hdc 103 + # mkudffs /dev/pktcdvd/dev_name 104 + # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram 105 + # cp files /dvdram 106 + # umount /dvdram 107 + # pktcdvd -r dev_name 108 + 109 + 110 + For a description of the sysfs interface look into the file: 111 + 112 + Documentation/ABI/testing/sysfs-block-pktcdvd 113 + 114 + 115 + Using the pktcdvd debugfs interface 116 + ----------------------------------- 117 + 118 + To read pktcdvd device infos in human readable form, do: 119 + 120 + # cat /debug/pktcdvd/pktcdvd[0-7]/info 121 + 122 + For a description of the debugfs interface look into the file: 123 + 124 + Documentation/ABI/testing/debugfs-pktcdvd 125 + 126 + 127 + 93 128 Links 94 129 ----- 95 130
+439 -4
drivers/block/pktcdvd.c
··· 60 60 #include <scsi/scsi_cmnd.h> 61 61 #include <scsi/scsi_ioctl.h> 62 62 #include <scsi/scsi.h> 63 + #include <linux/debugfs.h> 64 + #include <linux/device.h> 63 65 64 66 #include <asm/uaccess.h> 65 67 ··· 90 88 static int write_congestion_off = PKT_WRITE_CONGESTION_OFF; 91 89 static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ 92 90 static mempool_t *psd_pool; 91 + 92 + static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ 93 + static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */ 94 + 95 + /* forward declaration */ 96 + static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); 97 + static int pkt_remove_dev(dev_t pkt_dev); 98 + static int pkt_seq_show(struct seq_file *m, void *p); 99 + 100 + 101 + 102 + /* 103 + * create and register a pktcdvd kernel object. 104 + */ 105 + static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd, 106 + const char* name, 107 + struct kobject* parent, 108 + struct kobj_type* ktype) 109 + { 110 + struct pktcdvd_kobj *p; 111 + p = kzalloc(sizeof(*p), GFP_KERNEL); 112 + if (!p) 113 + return NULL; 114 + kobject_set_name(&p->kobj, "%s", name); 115 + p->kobj.parent = parent; 116 + p->kobj.ktype = ktype; 117 + p->pd = pd; 118 + if (kobject_register(&p->kobj) != 0) 119 + return NULL; 120 + return p; 121 + } 122 + /* 123 + * remove a pktcdvd kernel object. 124 + */ 125 + static void pkt_kobj_remove(struct pktcdvd_kobj *p) 126 + { 127 + if (p) 128 + kobject_unregister(&p->kobj); 129 + } 130 + /* 131 + * default release function for pktcdvd kernel objects. 132 + */ 133 + static void pkt_kobj_release(struct kobject *kobj) 134 + { 135 + kfree(to_pktcdvdkobj(kobj)); 136 + } 137 + 138 + 139 + /********************************************************** 140 + * 141 + * sysfs interface for pktcdvd 142 + * by (C) 2006 Thomas Maier <balagi@justmail.de> 143 + * 144 + **********************************************************/ 145 + 146 + #define DEF_ATTR(_obj,_name,_mode) \ 147 + static struct attribute _obj = { \ 148 + .name = _name, .owner = THIS_MODULE, .mode = _mode } 149 + 150 + /********************************************************** 151 + /sys/class/pktcdvd/pktcdvd[0-7]/ 152 + stat/reset 153 + stat/packets_started 154 + stat/packets_finished 155 + stat/kb_written 156 + stat/kb_read 157 + stat/kb_read_gather 158 + write_queue/size 159 + write_queue/congestion_off 160 + write_queue/congestion_on 161 + **********************************************************/ 162 + 163 + DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200); 164 + DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444); 165 + DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444); 166 + DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444); 167 + DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444); 168 + DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444); 169 + 170 + static struct attribute *kobj_pkt_attrs_stat[] = { 171 + &kobj_pkt_attr_st1, 172 + &kobj_pkt_attr_st2, 173 + &kobj_pkt_attr_st3, 174 + &kobj_pkt_attr_st4, 175 + &kobj_pkt_attr_st5, 176 + &kobj_pkt_attr_st6, 177 + NULL 178 + }; 179 + 180 + DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444); 181 + DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644); 182 + DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644); 183 + 184 + static struct attribute *kobj_pkt_attrs_wqueue[] = { 185 + &kobj_pkt_attr_wq1, 186 + &kobj_pkt_attr_wq2, 187 + &kobj_pkt_attr_wq3, 188 + NULL 189 + }; 190 + 191 + /* declares a char buffer[64] _dbuf, copies data from 192 + * _b with length _l into it and ensures that _dbuf ends 193 + * with a \0 character. 194 + */ 195 + #define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \ 196 + char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \ 197 + if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \ 198 + memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0 199 + 200 + static ssize_t kobj_pkt_show(struct kobject *kobj, 201 + struct attribute *attr, char *data) 202 + { 203 + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; 204 + int n = 0; 205 + int v; 206 + if (strcmp(attr->name, "packets_started") == 0) { 207 + n = sprintf(data, "%lu\n", pd->stats.pkt_started); 208 + 209 + } else if (strcmp(attr->name, "packets_finished") == 0) { 210 + n = sprintf(data, "%lu\n", pd->stats.pkt_ended); 211 + 212 + } else if (strcmp(attr->name, "kb_written") == 0) { 213 + n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1); 214 + 215 + } else if (strcmp(attr->name, "kb_read") == 0) { 216 + n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1); 217 + 218 + } else if (strcmp(attr->name, "kb_read_gather") == 0) { 219 + n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1); 220 + 221 + } else if (strcmp(attr->name, "size") == 0) { 222 + spin_lock(&pd->lock); 223 + v = pd->bio_queue_size; 224 + spin_unlock(&pd->lock); 225 + n = sprintf(data, "%d\n", v); 226 + 227 + } else if (strcmp(attr->name, "congestion_off") == 0) { 228 + spin_lock(&pd->lock); 229 + v = pd->write_congestion_off; 230 + spin_unlock(&pd->lock); 231 + n = sprintf(data, "%d\n", v); 232 + 233 + } else if (strcmp(attr->name, "congestion_on") == 0) { 234 + spin_lock(&pd->lock); 235 + v = pd->write_congestion_on; 236 + spin_unlock(&pd->lock); 237 + n = sprintf(data, "%d\n", v); 238 + } 239 + return n; 240 + } 241 + 242 + static void init_write_congestion_marks(int* lo, int* hi) 243 + { 244 + if (*hi > 0) { 245 + *hi = max(*hi, 500); 246 + *hi = min(*hi, 1000000); 247 + if (*lo <= 0) 248 + *lo = *hi - 100; 249 + else { 250 + *lo = min(*lo, *hi - 100); 251 + *lo = max(*lo, 100); 252 + } 253 + } else { 254 + *hi = -1; 255 + *lo = -1; 256 + } 257 + } 258 + 259 + static ssize_t kobj_pkt_store(struct kobject *kobj, 260 + struct attribute *attr, 261 + const char *data, size_t len) 262 + { 263 + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; 264 + int val; 265 + DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */ 266 + 267 + if (strcmp(attr->name, "reset") == 0 && dlen > 0) { 268 + pd->stats.pkt_started = 0; 269 + pd->stats.pkt_ended = 0; 270 + pd->stats.secs_w = 0; 271 + pd->stats.secs_rg = 0; 272 + pd->stats.secs_r = 0; 273 + 274 + } else if (strcmp(attr->name, "congestion_off") == 0 275 + && sscanf(dbuf, "%d", &val) == 1) { 276 + spin_lock(&pd->lock); 277 + pd->write_congestion_off = val; 278 + init_write_congestion_marks(&pd->write_congestion_off, 279 + &pd->write_congestion_on); 280 + spin_unlock(&pd->lock); 281 + 282 + } else if (strcmp(attr->name, "congestion_on") == 0 283 + && sscanf(dbuf, "%d", &val) == 1) { 284 + spin_lock(&pd->lock); 285 + pd->write_congestion_on = val; 286 + init_write_congestion_marks(&pd->write_congestion_off, 287 + &pd->write_congestion_on); 288 + spin_unlock(&pd->lock); 289 + } 290 + return len; 291 + } 292 + 293 + static struct sysfs_ops kobj_pkt_ops = { 294 + .show = kobj_pkt_show, 295 + .store = kobj_pkt_store 296 + }; 297 + static struct kobj_type kobj_pkt_type_stat = { 298 + .release = pkt_kobj_release, 299 + .sysfs_ops = &kobj_pkt_ops, 300 + .default_attrs = kobj_pkt_attrs_stat 301 + }; 302 + static struct kobj_type kobj_pkt_type_wqueue = { 303 + .release = pkt_kobj_release, 304 + .sysfs_ops = &kobj_pkt_ops, 305 + .default_attrs = kobj_pkt_attrs_wqueue 306 + }; 307 + 308 + static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) 309 + { 310 + if (class_pktcdvd) { 311 + pd->clsdev = class_device_create(class_pktcdvd, 312 + NULL, pd->pkt_dev, 313 + NULL, "%s", pd->name); 314 + if (IS_ERR(pd->clsdev)) 315 + pd->clsdev = NULL; 316 + } 317 + if (pd->clsdev) { 318 + pd->kobj_stat = pkt_kobj_create(pd, "stat", 319 + &pd->clsdev->kobj, 320 + &kobj_pkt_type_stat); 321 + pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue", 322 + &pd->clsdev->kobj, 323 + &kobj_pkt_type_wqueue); 324 + } 325 + } 326 + 327 + static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd) 328 + { 329 + pkt_kobj_remove(pd->kobj_stat); 330 + pkt_kobj_remove(pd->kobj_wqueue); 331 + if (class_pktcdvd) 332 + class_device_destroy(class_pktcdvd, pd->pkt_dev); 333 + } 334 + 335 + 336 + /******************************************************************** 337 + /sys/class/pktcdvd/ 338 + add map block device 339 + remove unmap packet dev 340 + device_map show mappings 341 + *******************************************************************/ 342 + 343 + static void class_pktcdvd_release(struct class *cls) 344 + { 345 + kfree(cls); 346 + } 347 + static ssize_t class_pktcdvd_show_map(struct class *c, char *data) 348 + { 349 + int n = 0; 350 + int idx; 351 + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 352 + for (idx = 0; idx < MAX_WRITERS; idx++) { 353 + struct pktcdvd_device *pd = pkt_devs[idx]; 354 + if (!pd) 355 + continue; 356 + n += sprintf(data+n, "%s %u:%u %u:%u\n", 357 + pd->name, 358 + MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev), 359 + MAJOR(pd->bdev->bd_dev), 360 + MINOR(pd->bdev->bd_dev)); 361 + } 362 + mutex_unlock(&ctl_mutex); 363 + return n; 364 + } 365 + 366 + static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, 367 + size_t count) 368 + { 369 + unsigned int major, minor; 370 + DECLARE_BUF_AS_STRING(dbuf, buf, count); 371 + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { 372 + pkt_setup_dev(MKDEV(major, minor), NULL); 373 + return count; 374 + } 375 + return -EINVAL; 376 + } 377 + 378 + static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf, 379 + size_t count) 380 + { 381 + unsigned int major, minor; 382 + DECLARE_BUF_AS_STRING(dbuf, buf, count); 383 + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { 384 + pkt_remove_dev(MKDEV(major, minor)); 385 + return count; 386 + } 387 + return -EINVAL; 388 + } 389 + 390 + static struct class_attribute class_pktcdvd_attrs[] = { 391 + __ATTR(add, 0200, NULL, class_pktcdvd_store_add), 392 + __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove), 393 + __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL), 394 + __ATTR_NULL 395 + }; 396 + 397 + 398 + static int pkt_sysfs_init(void) 399 + { 400 + int ret = 0; 401 + 402 + /* 403 + * create control files in sysfs 404 + * /sys/class/pktcdvd/... 405 + */ 406 + class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL); 407 + if (!class_pktcdvd) 408 + return -ENOMEM; 409 + class_pktcdvd->name = DRIVER_NAME; 410 + class_pktcdvd->owner = THIS_MODULE; 411 + class_pktcdvd->class_release = class_pktcdvd_release; 412 + class_pktcdvd->class_attrs = class_pktcdvd_attrs; 413 + ret = class_register(class_pktcdvd); 414 + if (ret) { 415 + kfree(class_pktcdvd); 416 + class_pktcdvd = NULL; 417 + printk(DRIVER_NAME": failed to create class pktcdvd\n"); 418 + return ret; 419 + } 420 + return 0; 421 + } 422 + 423 + static void pkt_sysfs_cleanup(void) 424 + { 425 + if (class_pktcdvd) 426 + class_destroy(class_pktcdvd); 427 + class_pktcdvd = NULL; 428 + } 429 + 430 + /******************************************************************** 431 + entries in debugfs 432 + 433 + /debugfs/pktcdvd[0-7]/ 434 + info 435 + 436 + *******************************************************************/ 437 + 438 + static int pkt_debugfs_seq_show(struct seq_file *m, void *p) 439 + { 440 + return pkt_seq_show(m, p); 441 + } 442 + 443 + static int pkt_debugfs_fops_open(struct inode *inode, struct file *file) 444 + { 445 + return single_open(file, pkt_debugfs_seq_show, inode->i_private); 446 + } 447 + 448 + static struct file_operations debug_fops = { 449 + .open = pkt_debugfs_fops_open, 450 + .read = seq_read, 451 + .llseek = seq_lseek, 452 + .release = single_release, 453 + .owner = THIS_MODULE, 454 + }; 455 + 456 + static void pkt_debugfs_dev_new(struct pktcdvd_device *pd) 457 + { 458 + if (!pkt_debugfs_root) 459 + return; 460 + pd->dfs_f_info = NULL; 461 + pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root); 462 + if (IS_ERR(pd->dfs_d_root)) { 463 + pd->dfs_d_root = NULL; 464 + return; 465 + } 466 + pd->dfs_f_info = debugfs_create_file("info", S_IRUGO, 467 + pd->dfs_d_root, pd, &debug_fops); 468 + if (IS_ERR(pd->dfs_f_info)) { 469 + pd->dfs_f_info = NULL; 470 + return; 471 + } 472 + } 473 + 474 + static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd) 475 + { 476 + if (!pkt_debugfs_root) 477 + return; 478 + if (pd->dfs_f_info) 479 + debugfs_remove(pd->dfs_f_info); 480 + pd->dfs_f_info = NULL; 481 + if (pd->dfs_d_root) 482 + debugfs_remove(pd->dfs_d_root); 483 + pd->dfs_d_root = NULL; 484 + } 485 + 486 + static void pkt_debugfs_init(void) 487 + { 488 + pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL); 489 + if (IS_ERR(pkt_debugfs_root)) { 490 + pkt_debugfs_root = NULL; 491 + return; 492 + } 493 + } 494 + 495 + static void pkt_debugfs_cleanup(void) 496 + { 497 + if (!pkt_debugfs_root) 498 + return; 499 + debugfs_remove(pkt_debugfs_root); 500 + pkt_debugfs_root = NULL; 501 + } 502 + 503 + /* ----------------------------------------------------------*/ 93 504 94 505 95 506 static void pkt_bio_finished(struct pktcdvd_device *pd) ··· 2942 2527 2943 2528 add_disk(disk); 2944 2529 2530 + pkt_sysfs_dev_new(pd); 2531 + pkt_debugfs_dev_new(pd); 2532 + 2945 2533 pkt_devs[idx] = pd; 2946 2534 if (pkt_dev) 2947 2535 *pkt_dev = pd->pkt_dev; ··· 2995 2577 if (!IS_ERR(pd->cdrw.thread)) 2996 2578 kthread_stop(pd->cdrw.thread); 2997 2579 2580 + pkt_devs[idx] = NULL; 2581 + 2582 + pkt_debugfs_dev_remove(pd); 2583 + pkt_sysfs_dev_remove(pd); 2584 + 2998 2585 blkdev_put(pd->bdev); 2999 2586 3000 2587 remove_proc_entry(pd->name, pkt_proc); ··· 3009 2586 blk_cleanup_queue(pd->disk->queue); 3010 2587 put_disk(pd->disk); 3011 2588 3012 - pkt_devs[idx] = NULL; 3013 2589 mempool_destroy(pd->rb_pool); 3014 2590 kfree(pd); 3015 2591 ··· 3092 2670 { 3093 2671 int ret; 3094 2672 2673 + mutex_init(&ctl_mutex); 2674 + 3095 2675 psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE, 3096 2676 sizeof(struct packet_stacked_data)); 3097 2677 if (!psd_pool) ··· 3107 2683 if (!pktdev_major) 3108 2684 pktdev_major = ret; 3109 2685 2686 + ret = pkt_sysfs_init(); 2687 + if (ret) 2688 + goto out; 2689 + 2690 + pkt_debugfs_init(); 2691 + 3110 2692 ret = misc_register(&pkt_misc); 3111 2693 if (ret) { 3112 2694 printk(DRIVER_NAME": Unable to register misc device\n"); 3113 - goto out; 2695 + goto out_misc; 3114 2696 } 3115 - 3116 - mutex_init(&ctl_mutex); 3117 2697 3118 2698 pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver); 3119 2699 3120 2700 return 0; 3121 2701 2702 + out_misc: 2703 + pkt_debugfs_cleanup(); 2704 + pkt_sysfs_cleanup(); 3122 2705 out: 3123 2706 unregister_blkdev(pktdev_major, DRIVER_NAME); 3124 2707 out2: ··· 3137 2706 { 3138 2707 remove_proc_entry(DRIVER_NAME, proc_root_driver); 3139 2708 misc_deregister(&pkt_misc); 2709 + 2710 + pkt_debugfs_cleanup(); 2711 + pkt_sysfs_cleanup(); 2712 + 3140 2713 unregister_blkdev(pktdev_major, DRIVER_NAME); 3141 2714 mempool_destroy(psd_pool); 3142 2715 }
+17 -1
include/linux/pktcdvd.h
··· 111 111 #include <linux/blkdev.h> 112 112 #include <linux/completion.h> 113 113 #include <linux/cdrom.h> 114 - 114 + #include <linux/kobject.h> 115 + #include <linux/sysfs.h> 115 116 116 117 /* default bio write queue congestion marks */ 117 118 #define PKT_WRITE_CONGESTION_ON 10000 ··· 248 247 }; 249 248 #define PSD_POOL_SIZE 64 250 249 250 + struct pktcdvd_kobj 251 + { 252 + struct kobject kobj; 253 + struct pktcdvd_device *pd; 254 + }; 255 + #define to_pktcdvdkobj(_k) \ 256 + ((struct pktcdvd_kobj*)container_of(_k,struct pktcdvd_kobj,kobj)) 257 + 251 258 struct pktcdvd_device 252 259 { 253 260 struct block_device *bdev; /* dev attached */ ··· 289 280 290 281 int write_congestion_off; 291 282 int write_congestion_on; 283 + 284 + struct class_device *clsdev; /* sysfs pktcdvd[0-7] class dev */ 285 + struct pktcdvd_kobj *kobj_stat; /* sysfs pktcdvd[0-7]/stat/ */ 286 + struct pktcdvd_kobj *kobj_wqueue; /* sysfs pktcdvd[0-7]/write_queue/ */ 287 + 288 + struct dentry *dfs_d_root; /* debugfs: devname directory */ 289 + struct dentry *dfs_f_info; /* debugfs: info file */ 292 290 }; 293 291 294 292 #endif /* __KERNEL__ */