Commit 3d1ab40f4c20767afbd361b258a531d73e3e6fc2
1 parent
1cc9be68eb
Exists in
master
and in
4 other branches
[PATCH] elevator_t lifetime rules and sysfs fixes
Showing 5 changed files with 160 additions and 202 deletions Side-by-side Diff
block/as-iosched.c
... | ... | @@ -1709,11 +1709,6 @@ |
1709 | 1709 | /* |
1710 | 1710 | * sysfs parts below |
1711 | 1711 | */ |
1712 | -struct as_fs_entry { | |
1713 | - struct attribute attr; | |
1714 | - ssize_t (*show)(struct as_data *, char *); | |
1715 | - ssize_t (*store)(struct as_data *, const char *, size_t); | |
1716 | -}; | |
1717 | 1712 | |
1718 | 1713 | static ssize_t |
1719 | 1714 | as_var_show(unsigned int var, char *page) |
1720 | 1715 | |
... | ... | @@ -1730,8 +1725,9 @@ |
1730 | 1725 | return count; |
1731 | 1726 | } |
1732 | 1727 | |
1733 | -static ssize_t as_est_show(struct as_data *ad, char *page) | |
1728 | +static ssize_t as_est_show(elevator_t *e, char *page) | |
1734 | 1729 | { |
1730 | + struct as_data *ad = e->elevator_data; | |
1735 | 1731 | int pos = 0; |
1736 | 1732 | |
1737 | 1733 | pos += sprintf(page+pos, "%lu %% exit probability\n", |
1738 | 1734 | |
... | ... | @@ -1747,8 +1743,9 @@ |
1747 | 1743 | } |
1748 | 1744 | |
1749 | 1745 | #define SHOW_FUNCTION(__FUNC, __VAR) \ |
1750 | -static ssize_t __FUNC(struct as_data *ad, char *page) \ | |
1746 | +static ssize_t __FUNC(elevator_t *e, char *page) \ | |
1751 | 1747 | { \ |
1748 | + struct as_data *ad = e->elevator_data; \ | |
1752 | 1749 | return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ |
1753 | 1750 | } |
1754 | 1751 | SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); |
1755 | 1752 | |
... | ... | @@ -1759,9 +1756,10 @@ |
1759 | 1756 | #undef SHOW_FUNCTION |
1760 | 1757 | |
1761 | 1758 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ |
1762 | -static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \ | |
1759 | +static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ | |
1763 | 1760 | { \ |
1764 | - int ret = as_var_store(__PTR, (page), count); \ | |
1761 | + struct as_data *ad = e->elevator_data; \ | |
1762 | + int ret = as_var_store(__PTR, (page), count); \ | |
1765 | 1763 | if (*(__PTR) < (MIN)) \ |
1766 | 1764 | *(__PTR) = (MIN); \ |
1767 | 1765 | else if (*(__PTR) > (MAX)) \ |
1768 | 1766 | |
1769 | 1767 | |
1770 | 1768 | |
1771 | 1769 | |
1772 | 1770 | |
1773 | 1771 | |
... | ... | @@ -1778,37 +1776,37 @@ |
1778 | 1776 | &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); |
1779 | 1777 | #undef STORE_FUNCTION |
1780 | 1778 | |
1781 | -static struct as_fs_entry as_est_entry = { | |
1779 | +static struct elv_fs_entry as_est_entry = { | |
1782 | 1780 | .attr = {.name = "est_time", .mode = S_IRUGO }, |
1783 | 1781 | .show = as_est_show, |
1784 | 1782 | }; |
1785 | -static struct as_fs_entry as_readexpire_entry = { | |
1783 | +static struct elv_fs_entry as_readexpire_entry = { | |
1786 | 1784 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, |
1787 | 1785 | .show = as_readexpire_show, |
1788 | 1786 | .store = as_readexpire_store, |
1789 | 1787 | }; |
1790 | -static struct as_fs_entry as_writeexpire_entry = { | |
1788 | +static struct elv_fs_entry as_writeexpire_entry = { | |
1791 | 1789 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, |
1792 | 1790 | .show = as_writeexpire_show, |
1793 | 1791 | .store = as_writeexpire_store, |
1794 | 1792 | }; |
1795 | -static struct as_fs_entry as_anticexpire_entry = { | |
1793 | +static struct elv_fs_entry as_anticexpire_entry = { | |
1796 | 1794 | .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR }, |
1797 | 1795 | .show = as_anticexpire_show, |
1798 | 1796 | .store = as_anticexpire_store, |
1799 | 1797 | }; |
1800 | -static struct as_fs_entry as_read_batchexpire_entry = { | |
1798 | +static struct elv_fs_entry as_read_batchexpire_entry = { | |
1801 | 1799 | .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR }, |
1802 | 1800 | .show = as_read_batchexpire_show, |
1803 | 1801 | .store = as_read_batchexpire_store, |
1804 | 1802 | }; |
1805 | -static struct as_fs_entry as_write_batchexpire_entry = { | |
1803 | +static struct elv_fs_entry as_write_batchexpire_entry = { | |
1806 | 1804 | .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR }, |
1807 | 1805 | .show = as_write_batchexpire_show, |
1808 | 1806 | .store = as_write_batchexpire_store, |
1809 | 1807 | }; |
1810 | 1808 | |
1811 | -static struct attribute *default_attrs[] = { | |
1809 | +static struct attribute *as_attrs[] = { | |
1812 | 1810 | &as_est_entry.attr, |
1813 | 1811 | &as_readexpire_entry.attr, |
1814 | 1812 | &as_writeexpire_entry.attr, |
... | ... | @@ -1818,43 +1816,6 @@ |
1818 | 1816 | NULL, |
1819 | 1817 | }; |
1820 | 1818 | |
1821 | -#define to_as(atr) container_of((atr), struct as_fs_entry, attr) | |
1822 | - | |
1823 | -static ssize_t | |
1824 | -as_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | |
1825 | -{ | |
1826 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
1827 | - struct as_fs_entry *entry = to_as(attr); | |
1828 | - | |
1829 | - if (!entry->show) | |
1830 | - return -EIO; | |
1831 | - | |
1832 | - return entry->show(e->elevator_data, page); | |
1833 | -} | |
1834 | - | |
1835 | -static ssize_t | |
1836 | -as_attr_store(struct kobject *kobj, struct attribute *attr, | |
1837 | - const char *page, size_t length) | |
1838 | -{ | |
1839 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
1840 | - struct as_fs_entry *entry = to_as(attr); | |
1841 | - | |
1842 | - if (!entry->store) | |
1843 | - return -EIO; | |
1844 | - | |
1845 | - return entry->store(e->elevator_data, page, length); | |
1846 | -} | |
1847 | - | |
1848 | -static struct sysfs_ops as_sysfs_ops = { | |
1849 | - .show = as_attr_show, | |
1850 | - .store = as_attr_store, | |
1851 | -}; | |
1852 | - | |
1853 | -static struct kobj_type as_ktype = { | |
1854 | - .sysfs_ops = &as_sysfs_ops, | |
1855 | - .default_attrs = default_attrs, | |
1856 | -}; | |
1857 | - | |
1858 | 1819 | static struct elevator_type iosched_as = { |
1859 | 1820 | .ops = { |
1860 | 1821 | .elevator_merge_fn = as_merge, |
... | ... | @@ -1876,7 +1837,7 @@ |
1876 | 1837 | .trim = as_trim, |
1877 | 1838 | }, |
1878 | 1839 | |
1879 | - .elevator_ktype = &as_ktype, | |
1840 | + .elevator_attrs = as_attrs, | |
1880 | 1841 | .elevator_name = "anticipatory", |
1881 | 1842 | .elevator_owner = THIS_MODULE, |
1882 | 1843 | }; |
block/cfq-iosched.c
... | ... | @@ -2275,11 +2275,6 @@ |
2275 | 2275 | /* |
2276 | 2276 | * sysfs parts below --> |
2277 | 2277 | */ |
2278 | -struct cfq_fs_entry { | |
2279 | - struct attribute attr; | |
2280 | - ssize_t (*show)(struct cfq_data *, char *); | |
2281 | - ssize_t (*store)(struct cfq_data *, const char *, size_t); | |
2282 | -}; | |
2283 | 2278 | |
2284 | 2279 | static ssize_t |
2285 | 2280 | cfq_var_show(unsigned int var, char *page) |
2286 | 2281 | |
... | ... | @@ -2297,8 +2292,9 @@ |
2297 | 2292 | } |
2298 | 2293 | |
2299 | 2294 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ |
2300 | -static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ | |
2295 | +static ssize_t __FUNC(elevator_t *e, char *page) \ | |
2301 | 2296 | { \ |
2297 | + struct cfq_data *cfqd = e->elevator_data; \ | |
2302 | 2298 | unsigned int __data = __VAR; \ |
2303 | 2299 | if (__CONV) \ |
2304 | 2300 | __data = jiffies_to_msecs(__data); \ |
2305 | 2301 | |
... | ... | @@ -2318,8 +2314,9 @@ |
2318 | 2314 | #undef SHOW_FUNCTION |
2319 | 2315 | |
2320 | 2316 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ |
2321 | -static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ | |
2317 | +static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ | |
2322 | 2318 | { \ |
2319 | + struct cfq_data *cfqd = e->elevator_data; \ | |
2323 | 2320 | unsigned int __data; \ |
2324 | 2321 | int ret = cfq_var_store(&__data, (page), count); \ |
2325 | 2322 | if (__data < (MIN)) \ |
2326 | 2323 | |
2327 | 2324 | |
2328 | 2325 | |
2329 | 2326 | |
2330 | 2327 | |
2331 | 2328 | |
2332 | 2329 | |
2333 | 2330 | |
2334 | 2331 | |
2335 | 2332 | |
2336 | 2333 | |
... | ... | @@ -2345,63 +2342,63 @@ |
2345 | 2342 | STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); |
2346 | 2343 | #undef STORE_FUNCTION |
2347 | 2344 | |
2348 | -static struct cfq_fs_entry cfq_quantum_entry = { | |
2345 | +static struct elv_fs_entry cfq_quantum_entry = { | |
2349 | 2346 | .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, |
2350 | 2347 | .show = cfq_quantum_show, |
2351 | 2348 | .store = cfq_quantum_store, |
2352 | 2349 | }; |
2353 | -static struct cfq_fs_entry cfq_queued_entry = { | |
2350 | +static struct elv_fs_entry cfq_queued_entry = { | |
2354 | 2351 | .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, |
2355 | 2352 | .show = cfq_queued_show, |
2356 | 2353 | .store = cfq_queued_store, |
2357 | 2354 | }; |
2358 | -static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { | |
2355 | +static struct elv_fs_entry cfq_fifo_expire_sync_entry = { | |
2359 | 2356 | .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, |
2360 | 2357 | .show = cfq_fifo_expire_sync_show, |
2361 | 2358 | .store = cfq_fifo_expire_sync_store, |
2362 | 2359 | }; |
2363 | -static struct cfq_fs_entry cfq_fifo_expire_async_entry = { | |
2360 | +static struct elv_fs_entry cfq_fifo_expire_async_entry = { | |
2364 | 2361 | .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, |
2365 | 2362 | .show = cfq_fifo_expire_async_show, |
2366 | 2363 | .store = cfq_fifo_expire_async_store, |
2367 | 2364 | }; |
2368 | -static struct cfq_fs_entry cfq_back_max_entry = { | |
2365 | +static struct elv_fs_entry cfq_back_max_entry = { | |
2369 | 2366 | .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, |
2370 | 2367 | .show = cfq_back_max_show, |
2371 | 2368 | .store = cfq_back_max_store, |
2372 | 2369 | }; |
2373 | -static struct cfq_fs_entry cfq_back_penalty_entry = { | |
2370 | +static struct elv_fs_entry cfq_back_penalty_entry = { | |
2374 | 2371 | .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, |
2375 | 2372 | .show = cfq_back_penalty_show, |
2376 | 2373 | .store = cfq_back_penalty_store, |
2377 | 2374 | }; |
2378 | -static struct cfq_fs_entry cfq_slice_sync_entry = { | |
2375 | +static struct elv_fs_entry cfq_slice_sync_entry = { | |
2379 | 2376 | .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, |
2380 | 2377 | .show = cfq_slice_sync_show, |
2381 | 2378 | .store = cfq_slice_sync_store, |
2382 | 2379 | }; |
2383 | -static struct cfq_fs_entry cfq_slice_async_entry = { | |
2380 | +static struct elv_fs_entry cfq_slice_async_entry = { | |
2384 | 2381 | .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, |
2385 | 2382 | .show = cfq_slice_async_show, |
2386 | 2383 | .store = cfq_slice_async_store, |
2387 | 2384 | }; |
2388 | -static struct cfq_fs_entry cfq_slice_async_rq_entry = { | |
2385 | +static struct elv_fs_entry cfq_slice_async_rq_entry = { | |
2389 | 2386 | .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, |
2390 | 2387 | .show = cfq_slice_async_rq_show, |
2391 | 2388 | .store = cfq_slice_async_rq_store, |
2392 | 2389 | }; |
2393 | -static struct cfq_fs_entry cfq_slice_idle_entry = { | |
2390 | +static struct elv_fs_entry cfq_slice_idle_entry = { | |
2394 | 2391 | .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, |
2395 | 2392 | .show = cfq_slice_idle_show, |
2396 | 2393 | .store = cfq_slice_idle_store, |
2397 | 2394 | }; |
2398 | -static struct cfq_fs_entry cfq_max_depth_entry = { | |
2395 | +static struct elv_fs_entry cfq_max_depth_entry = { | |
2399 | 2396 | .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, |
2400 | 2397 | .show = cfq_max_depth_show, |
2401 | 2398 | .store = cfq_max_depth_store, |
2402 | 2399 | }; |
2403 | 2400 | |
2404 | -static struct attribute *default_attrs[] = { | |
2401 | +static struct attribute *cfq_attrs[] = { | |
2405 | 2402 | &cfq_quantum_entry.attr, |
2406 | 2403 | &cfq_queued_entry.attr, |
2407 | 2404 | &cfq_fifo_expire_sync_entry.attr, |
... | ... | @@ -2416,43 +2413,6 @@ |
2416 | 2413 | NULL, |
2417 | 2414 | }; |
2418 | 2415 | |
2419 | -#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr) | |
2420 | - | |
2421 | -static ssize_t | |
2422 | -cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | |
2423 | -{ | |
2424 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
2425 | - struct cfq_fs_entry *entry = to_cfq(attr); | |
2426 | - | |
2427 | - if (!entry->show) | |
2428 | - return -EIO; | |
2429 | - | |
2430 | - return entry->show(e->elevator_data, page); | |
2431 | -} | |
2432 | - | |
2433 | -static ssize_t | |
2434 | -cfq_attr_store(struct kobject *kobj, struct attribute *attr, | |
2435 | - const char *page, size_t length) | |
2436 | -{ | |
2437 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
2438 | - struct cfq_fs_entry *entry = to_cfq(attr); | |
2439 | - | |
2440 | - if (!entry->store) | |
2441 | - return -EIO; | |
2442 | - | |
2443 | - return entry->store(e->elevator_data, page, length); | |
2444 | -} | |
2445 | - | |
2446 | -static struct sysfs_ops cfq_sysfs_ops = { | |
2447 | - .show = cfq_attr_show, | |
2448 | - .store = cfq_attr_store, | |
2449 | -}; | |
2450 | - | |
2451 | -static struct kobj_type cfq_ktype = { | |
2452 | - .sysfs_ops = &cfq_sysfs_ops, | |
2453 | - .default_attrs = default_attrs, | |
2454 | -}; | |
2455 | - | |
2456 | 2416 | static struct elevator_type iosched_cfq = { |
2457 | 2417 | .ops = { |
2458 | 2418 | .elevator_merge_fn = cfq_merge, |
... | ... | @@ -2473,7 +2433,7 @@ |
2473 | 2433 | .elevator_exit_fn = cfq_exit_queue, |
2474 | 2434 | .trim = cfq_trim, |
2475 | 2435 | }, |
2476 | - .elevator_ktype = &cfq_ktype, | |
2436 | + .elevator_attrs = cfq_attrs, | |
2477 | 2437 | .elevator_name = "cfq", |
2478 | 2438 | .elevator_owner = THIS_MODULE, |
2479 | 2439 | }; |
block/deadline-iosched.c
... | ... | @@ -694,11 +694,6 @@ |
694 | 694 | /* |
695 | 695 | * sysfs parts below |
696 | 696 | */ |
697 | -struct deadline_fs_entry { | |
698 | - struct attribute attr; | |
699 | - ssize_t (*show)(struct deadline_data *, char *); | |
700 | - ssize_t (*store)(struct deadline_data *, const char *, size_t); | |
701 | -}; | |
702 | 697 | |
703 | 698 | static ssize_t |
704 | 699 | deadline_var_show(int var, char *page) |
705 | 700 | |
... | ... | @@ -716,9 +711,10 @@ |
716 | 711 | } |
717 | 712 | |
718 | 713 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ |
719 | -static ssize_t __FUNC(struct deadline_data *dd, char *page) \ | |
714 | +static ssize_t __FUNC(elevator_t *e, char *page) \ | |
720 | 715 | { \ |
721 | - int __data = __VAR; \ | |
716 | + struct deadline_data *dd = e->elevator_data; \ | |
717 | + int __data = __VAR; \ | |
722 | 718 | if (__CONV) \ |
723 | 719 | __data = jiffies_to_msecs(__data); \ |
724 | 720 | return deadline_var_show(__data, (page)); \ |
725 | 721 | |
... | ... | @@ -731,8 +727,9 @@ |
731 | 727 | #undef SHOW_FUNCTION |
732 | 728 | |
733 | 729 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ |
734 | -static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \ | |
730 | +static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ | |
735 | 731 | { \ |
732 | + struct deadline_data *dd = e->elevator_data; \ | |
736 | 733 | int __data; \ |
737 | 734 | int ret = deadline_var_store(&__data, (page), count); \ |
738 | 735 | if (__data < (MIN)) \ |
739 | 736 | |
740 | 737 | |
741 | 738 | |
742 | 739 | |
743 | 740 | |
... | ... | @@ -752,33 +749,33 @@ |
752 | 749 | STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); |
753 | 750 | #undef STORE_FUNCTION |
754 | 751 | |
755 | -static struct deadline_fs_entry deadline_readexpire_entry = { | |
752 | +static struct elv_fs_entry deadline_readexpire_entry = { | |
756 | 753 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, |
757 | 754 | .show = deadline_readexpire_show, |
758 | 755 | .store = deadline_readexpire_store, |
759 | 756 | }; |
760 | -static struct deadline_fs_entry deadline_writeexpire_entry = { | |
757 | +static struct elv_fs_entry deadline_writeexpire_entry = { | |
761 | 758 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, |
762 | 759 | .show = deadline_writeexpire_show, |
763 | 760 | .store = deadline_writeexpire_store, |
764 | 761 | }; |
765 | -static struct deadline_fs_entry deadline_writesstarved_entry = { | |
762 | +static struct elv_fs_entry deadline_writesstarved_entry = { | |
766 | 763 | .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR }, |
767 | 764 | .show = deadline_writesstarved_show, |
768 | 765 | .store = deadline_writesstarved_store, |
769 | 766 | }; |
770 | -static struct deadline_fs_entry deadline_frontmerges_entry = { | |
767 | +static struct elv_fs_entry deadline_frontmerges_entry = { | |
771 | 768 | .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR }, |
772 | 769 | .show = deadline_frontmerges_show, |
773 | 770 | .store = deadline_frontmerges_store, |
774 | 771 | }; |
775 | -static struct deadline_fs_entry deadline_fifobatch_entry = { | |
772 | +static struct elv_fs_entry deadline_fifobatch_entry = { | |
776 | 773 | .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR }, |
777 | 774 | .show = deadline_fifobatch_show, |
778 | 775 | .store = deadline_fifobatch_store, |
779 | 776 | }; |
780 | 777 | |
781 | -static struct attribute *default_attrs[] = { | |
778 | +static struct attribute *deadline_attrs[] = { | |
782 | 779 | &deadline_readexpire_entry.attr, |
783 | 780 | &deadline_writeexpire_entry.attr, |
784 | 781 | &deadline_writesstarved_entry.attr, |
... | ... | @@ -787,43 +784,6 @@ |
787 | 784 | NULL, |
788 | 785 | }; |
789 | 786 | |
790 | -#define to_deadline(atr) container_of((atr), struct deadline_fs_entry, attr) | |
791 | - | |
792 | -static ssize_t | |
793 | -deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | |
794 | -{ | |
795 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
796 | - struct deadline_fs_entry *entry = to_deadline(attr); | |
797 | - | |
798 | - if (!entry->show) | |
799 | - return -EIO; | |
800 | - | |
801 | - return entry->show(e->elevator_data, page); | |
802 | -} | |
803 | - | |
804 | -static ssize_t | |
805 | -deadline_attr_store(struct kobject *kobj, struct attribute *attr, | |
806 | - const char *page, size_t length) | |
807 | -{ | |
808 | - elevator_t *e = container_of(kobj, elevator_t, kobj); | |
809 | - struct deadline_fs_entry *entry = to_deadline(attr); | |
810 | - | |
811 | - if (!entry->store) | |
812 | - return -EIO; | |
813 | - | |
814 | - return entry->store(e->elevator_data, page, length); | |
815 | -} | |
816 | - | |
817 | -static struct sysfs_ops deadline_sysfs_ops = { | |
818 | - .show = deadline_attr_show, | |
819 | - .store = deadline_attr_store, | |
820 | -}; | |
821 | - | |
822 | -static struct kobj_type deadline_ktype = { | |
823 | - .sysfs_ops = &deadline_sysfs_ops, | |
824 | - .default_attrs = default_attrs, | |
825 | -}; | |
826 | - | |
827 | 787 | static struct elevator_type iosched_deadline = { |
828 | 788 | .ops = { |
829 | 789 | .elevator_merge_fn = deadline_merge, |
... | ... | @@ -840,7 +800,7 @@ |
840 | 800 | .elevator_exit_fn = deadline_exit_queue, |
841 | 801 | }, |
842 | 802 | |
843 | - .elevator_ktype = &deadline_ktype, | |
803 | + .elevator_attrs = deadline_attrs, | |
844 | 804 | .elevator_name = "deadline", |
845 | 805 | .elevator_owner = THIS_MODULE, |
846 | 806 | }; |
block/elevator.c
... | ... | @@ -120,15 +120,10 @@ |
120 | 120 | return e; |
121 | 121 | } |
122 | 122 | |
123 | -static int elevator_attach(request_queue_t *q, struct elevator_type *e, | |
124 | - struct elevator_queue *eq) | |
123 | +static int elevator_attach(request_queue_t *q, struct elevator_queue *eq) | |
125 | 124 | { |
126 | 125 | int ret = 0; |
127 | 126 | |
128 | - memset(eq, 0, sizeof(*eq)); | |
129 | - eq->ops = &e->ops; | |
130 | - eq->elevator_type = e; | |
131 | - | |
132 | 127 | q->elevator = eq; |
133 | 128 | |
134 | 129 | if (eq->ops->elevator_init_fn) |
... | ... | @@ -154,6 +149,32 @@ |
154 | 149 | |
155 | 150 | __setup("elevator=", elevator_setup); |
156 | 151 | |
152 | +static struct kobj_type elv_ktype; | |
153 | + | |
154 | +static elevator_t *elevator_alloc(struct elevator_type *e) | |
155 | +{ | |
156 | + elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL); | |
157 | + if (eq) { | |
158 | + memset(eq, 0, sizeof(*eq)); | |
159 | + eq->ops = &e->ops; | |
160 | + eq->elevator_type = e; | |
161 | + kobject_init(&eq->kobj); | |
162 | + snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); | |
163 | + eq->kobj.ktype = &elv_ktype; | |
164 | + mutex_init(&eq->sysfs_lock); | |
165 | + } else { | |
166 | + elevator_put(e); | |
167 | + } | |
168 | + return eq; | |
169 | +} | |
170 | + | |
171 | +static void elevator_release(struct kobject *kobj) | |
172 | +{ | |
173 | + elevator_t *e = container_of(kobj, elevator_t, kobj); | |
174 | + elevator_put(e->elevator_type); | |
175 | + kfree(e); | |
176 | +} | |
177 | + | |
157 | 178 | int elevator_init(request_queue_t *q, char *name) |
158 | 179 | { |
159 | 180 | struct elevator_type *e = NULL; |
160 | 181 | |
161 | 182 | |
162 | 183 | |
163 | 184 | |
164 | 185 | |
... | ... | @@ -176,29 +197,26 @@ |
176 | 197 | e = elevator_get("noop"); |
177 | 198 | } |
178 | 199 | |
179 | - eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); | |
180 | - if (!eq) { | |
181 | - elevator_put(e); | |
200 | + eq = elevator_alloc(e); | |
201 | + if (!eq) | |
182 | 202 | return -ENOMEM; |
183 | - } | |
184 | 203 | |
185 | - ret = elevator_attach(q, e, eq); | |
186 | - if (ret) { | |
187 | - kfree(eq); | |
188 | - elevator_put(e); | |
189 | - } | |
204 | + ret = elevator_attach(q, eq); | |
205 | + if (ret) | |
206 | + kobject_put(&eq->kobj); | |
190 | 207 | |
191 | 208 | return ret; |
192 | 209 | } |
193 | 210 | |
194 | 211 | void elevator_exit(elevator_t *e) |
195 | 212 | { |
213 | + mutex_lock(&e->sysfs_lock); | |
196 | 214 | if (e->ops->elevator_exit_fn) |
197 | 215 | e->ops->elevator_exit_fn(e); |
216 | + e->ops = NULL; | |
217 | + mutex_unlock(&e->sysfs_lock); | |
198 | 218 | |
199 | - elevator_put(e->elevator_type); | |
200 | - e->elevator_type = NULL; | |
201 | - kfree(e); | |
219 | + kobject_put(&e->kobj); | |
202 | 220 | } |
203 | 221 | |
204 | 222 | /* |
205 | 223 | |
206 | 224 | |
207 | 225 | |
208 | 226 | |
... | ... | @@ -627,26 +645,78 @@ |
627 | 645 | } |
628 | 646 | } |
629 | 647 | |
648 | +#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) | |
649 | + | |
650 | +static ssize_t | |
651 | +elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | |
652 | +{ | |
653 | + elevator_t *e = container_of(kobj, elevator_t, kobj); | |
654 | + struct elv_fs_entry *entry = to_elv(attr); | |
655 | + ssize_t error; | |
656 | + | |
657 | + if (!entry->show) | |
658 | + return -EIO; | |
659 | + | |
660 | + mutex_lock(&e->sysfs_lock); | |
661 | + error = e->ops ? entry->show(e, page) : -ENOENT; | |
662 | + mutex_unlock(&e->sysfs_lock); | |
663 | + return error; | |
664 | +} | |
665 | + | |
666 | +static ssize_t | |
667 | +elv_attr_store(struct kobject *kobj, struct attribute *attr, | |
668 | + const char *page, size_t length) | |
669 | +{ | |
670 | + elevator_t *e = container_of(kobj, elevator_t, kobj); | |
671 | + struct elv_fs_entry *entry = to_elv(attr); | |
672 | + ssize_t error; | |
673 | + | |
674 | + if (!entry->store) | |
675 | + return -EIO; | |
676 | + | |
677 | + mutex_lock(&e->sysfs_lock); | |
678 | + error = e->ops ? entry->store(e, page, length) : -ENOENT; | |
679 | + mutex_unlock(&e->sysfs_lock); | |
680 | + return error; | |
681 | +} | |
682 | + | |
683 | +static struct sysfs_ops elv_sysfs_ops = { | |
684 | + .show = elv_attr_show, | |
685 | + .store = elv_attr_store, | |
686 | +}; | |
687 | + | |
688 | +static struct kobj_type elv_ktype = { | |
689 | + .sysfs_ops = &elv_sysfs_ops, | |
690 | + .release = elevator_release, | |
691 | +}; | |
692 | + | |
630 | 693 | int elv_register_queue(struct request_queue *q) |
631 | 694 | { |
632 | 695 | elevator_t *e = q->elevator; |
696 | + int error; | |
633 | 697 | |
634 | - e->kobj.parent = kobject_get(&q->kobj); | |
635 | - if (!e->kobj.parent) | |
636 | - return -EBUSY; | |
698 | + e->kobj.parent = &q->kobj; | |
637 | 699 | |
638 | - snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); | |
639 | - e->kobj.ktype = e->elevator_type->elevator_ktype; | |
640 | - | |
641 | - return kobject_register(&e->kobj); | |
700 | + error = kobject_add(&e->kobj); | |
701 | + if (!error) { | |
702 | + struct attribute **attr = e->elevator_type->elevator_attrs; | |
703 | + if (attr) { | |
704 | + while (*attr) { | |
705 | + if (sysfs_create_file(&e->kobj,*attr++)) | |
706 | + break; | |
707 | + } | |
708 | + } | |
709 | + kobject_uevent(&e->kobj, KOBJ_ADD); | |
710 | + } | |
711 | + return error; | |
642 | 712 | } |
643 | 713 | |
644 | 714 | void elv_unregister_queue(struct request_queue *q) |
645 | 715 | { |
646 | 716 | if (q) { |
647 | 717 | elevator_t *e = q->elevator; |
648 | - kobject_unregister(&e->kobj); | |
649 | - kobject_put(&q->kobj); | |
718 | + kobject_uevent(&e->kobj, KOBJ_REMOVE); | |
719 | + kobject_del(&e->kobj); | |
650 | 720 | } |
651 | 721 | } |
652 | 722 | |
653 | 723 | |
654 | 724 | |
... | ... | @@ -697,16 +767,16 @@ |
697 | 767 | * need for the new one. this way we have a chance of going back to the old |
698 | 768 | * one, if the new one fails init for some reason. |
699 | 769 | */ |
700 | -static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) | |
770 | +static int elevator_switch(request_queue_t *q, struct elevator_type *new_e) | |
701 | 771 | { |
702 | 772 | elevator_t *old_elevator, *e; |
703 | 773 | |
704 | 774 | /* |
705 | 775 | * Allocate new elevator |
706 | 776 | */ |
707 | - e = kmalloc(sizeof(elevator_t), GFP_KERNEL); | |
777 | + e = elevator_alloc(new_e); | |
708 | 778 | if (!e) |
709 | - goto error; | |
779 | + return 0; | |
710 | 780 | |
711 | 781 | /* |
712 | 782 | * Turn on BYPASS and drain all requests w/ elevator private data |
... | ... | @@ -737,7 +807,7 @@ |
737 | 807 | /* |
738 | 808 | * attach and start new elevator |
739 | 809 | */ |
740 | - if (elevator_attach(q, new_e, e)) | |
810 | + if (elevator_attach(q, e)) | |
741 | 811 | goto fail; |
742 | 812 | |
743 | 813 | if (elv_register_queue(q)) |
... | ... | @@ -748,7 +818,7 @@ |
748 | 818 | */ |
749 | 819 | elevator_exit(old_elevator); |
750 | 820 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); |
751 | - return; | |
821 | + return 1; | |
752 | 822 | |
753 | 823 | fail_register: |
754 | 824 | /* |
... | ... | @@ -761,10 +831,9 @@ |
761 | 831 | q->elevator = old_elevator; |
762 | 832 | elv_register_queue(q); |
763 | 833 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); |
764 | - kfree(e); | |
765 | -error: | |
766 | - elevator_put(new_e); | |
767 | - printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); | |
834 | + if (e) | |
835 | + kobject_put(&e->kobj); | |
836 | + return 0; | |
768 | 837 | } |
769 | 838 | |
770 | 839 | ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) |
... | ... | @@ -791,7 +860,8 @@ |
791 | 860 | return count; |
792 | 861 | } |
793 | 862 | |
794 | - elevator_switch(q, e); | |
863 | + if (!elevator_switch(q, e)) | |
864 | + printk(KERN_ERR "elevator: switch to %s failed\n",elevator_name); | |
795 | 865 | return count; |
796 | 866 | } |
797 | 867 |
include/linux/elevator.h
... | ... | @@ -61,7 +61,7 @@ |
61 | 61 | struct list_head list; |
62 | 62 | struct elevator_ops ops; |
63 | 63 | struct elevator_type *elevator_type; |
64 | - struct kobj_type *elevator_ktype; | |
64 | + struct attribute **elevator_attrs; | |
65 | 65 | char elevator_name[ELV_NAME_MAX]; |
66 | 66 | struct module *elevator_owner; |
67 | 67 | }; |
... | ... | @@ -75,6 +75,7 @@ |
75 | 75 | void *elevator_data; |
76 | 76 | struct kobject kobj; |
77 | 77 | struct elevator_type *elevator_type; |
78 | + struct mutex sysfs_lock; | |
78 | 79 | }; |
79 | 80 | |
80 | 81 | /* |
... | ... | @@ -139,6 +140,12 @@ |
139 | 140 | ELV_MQUEUE_MAY, |
140 | 141 | ELV_MQUEUE_NO, |
141 | 142 | ELV_MQUEUE_MUST, |
143 | +}; | |
144 | + | |
145 | +struct elv_fs_entry { | |
146 | + struct attribute attr; | |
147 | + ssize_t (*show)(elevator_t *, char *); | |
148 | + ssize_t (*store)(elevator_t *, const char *, size_t); | |
142 | 149 | }; |
143 | 150 | |
144 | 151 | #define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) |