diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:35:43 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:35:43 -0500 |
| commit | 3d1ab40f4c20767afbd361b258a531d73e3e6fc2 (patch) | |
| tree | 2da79cc8b47a98b0496b6e762fa790a8d547977b /block | |
| parent | 1cc9be68ebcc1de9904bf225441613878da9c0d8 (diff) | |
[PATCH] elevator_t lifetime rules and sysfs fixes
Diffstat (limited to 'block')
| -rw-r--r-- | block/as-iosched.c | 69 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 74 | ||||
| -rw-r--r-- | block/deadline-iosched.c | 64 | ||||
| -rw-r--r-- | block/elevator.c | 146 |
4 files changed, 152 insertions, 201 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index 55a997fc4bb4..3fb60eb7093b 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
| @@ -1709,11 +1709,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e) | |||
| 1709 | /* | 1709 | /* |
| 1710 | * sysfs parts below | 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 | static ssize_t | 1713 | static ssize_t |
| 1719 | as_var_show(unsigned int var, char *page) | 1714 | as_var_show(unsigned int var, char *page) |
| @@ -1730,8 +1725,9 @@ as_var_store(unsigned long *var, const char *page, size_t count) | |||
| 1730 | return count; | 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 | int pos = 0; | 1731 | int pos = 0; |
| 1736 | 1732 | ||
| 1737 | pos += sprintf(page+pos, "%lu %% exit probability\n", | 1733 | pos += sprintf(page+pos, "%lu %% exit probability\n", |
| @@ -1747,8 +1743,9 @@ static ssize_t as_est_show(struct as_data *ad, char *page) | |||
| 1747 | } | 1743 | } |
| 1748 | 1744 | ||
| 1749 | #define SHOW_FUNCTION(__FUNC, __VAR) \ | 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 | return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ | 1749 | return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ |
| 1753 | } | 1750 | } |
| 1754 | SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); | 1751 | SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); |
| @@ -1759,9 +1756,10 @@ SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]); | |||
| 1759 | #undef SHOW_FUNCTION | 1756 | #undef SHOW_FUNCTION |
| 1760 | 1757 | ||
| 1761 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ | 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 | if (*(__PTR) < (MIN)) \ | 1763 | if (*(__PTR) < (MIN)) \ |
| 1766 | *(__PTR) = (MIN); \ | 1764 | *(__PTR) = (MIN); \ |
| 1767 | else if (*(__PTR) > (MAX)) \ | 1765 | else if (*(__PTR) > (MAX)) \ |
| @@ -1778,37 +1776,37 @@ STORE_FUNCTION(as_write_batchexpire_store, | |||
| 1778 | &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); | 1776 | &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); |
| 1779 | #undef STORE_FUNCTION | 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 | .attr = {.name = "est_time", .mode = S_IRUGO }, | 1780 | .attr = {.name = "est_time", .mode = S_IRUGO }, |
| 1783 | .show = as_est_show, | 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 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, | 1784 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, |
| 1787 | .show = as_readexpire_show, | 1785 | .show = as_readexpire_show, |
| 1788 | .store = as_readexpire_store, | 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 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, | 1789 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, |
| 1792 | .show = as_writeexpire_show, | 1790 | .show = as_writeexpire_show, |
| 1793 | .store = as_writeexpire_store, | 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 | .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR }, | 1794 | .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR }, |
| 1797 | .show = as_anticexpire_show, | 1795 | .show = as_anticexpire_show, |
| 1798 | .store = as_anticexpire_store, | 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 | .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR }, | 1799 | .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR }, |
| 1802 | .show = as_read_batchexpire_show, | 1800 | .show = as_read_batchexpire_show, |
| 1803 | .store = as_read_batchexpire_store, | 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 | .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR }, | 1804 | .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR }, |
| 1807 | .show = as_write_batchexpire_show, | 1805 | .show = as_write_batchexpire_show, |
| 1808 | .store = as_write_batchexpire_store, | 1806 | .store = as_write_batchexpire_store, |
| 1809 | }; | 1807 | }; |
| 1810 | 1808 | ||
| 1811 | static struct attribute *default_attrs[] = { | 1809 | static struct attribute *as_attrs[] = { |
| 1812 | &as_est_entry.attr, | 1810 | &as_est_entry.attr, |
| 1813 | &as_readexpire_entry.attr, | 1811 | &as_readexpire_entry.attr, |
| 1814 | &as_writeexpire_entry.attr, | 1812 | &as_writeexpire_entry.attr, |
| @@ -1818,43 +1816,6 @@ static struct attribute *default_attrs[] = { | |||
| 1818 | NULL, | 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 | static struct elevator_type iosched_as = { | 1819 | static struct elevator_type iosched_as = { |
| 1859 | .ops = { | 1820 | .ops = { |
| 1860 | .elevator_merge_fn = as_merge, | 1821 | .elevator_merge_fn = as_merge, |
| @@ -1876,7 +1837,7 @@ static struct elevator_type iosched_as = { | |||
| 1876 | .trim = as_trim, | 1837 | .trim = as_trim, |
| 1877 | }, | 1838 | }, |
| 1878 | 1839 | ||
| 1879 | .elevator_ktype = &as_ktype, | 1840 | .elevator_attrs = as_attrs, |
| 1880 | .elevator_name = "anticipatory", | 1841 | .elevator_name = "anticipatory", |
| 1881 | .elevator_owner = THIS_MODULE, | 1842 | .elevator_owner = THIS_MODULE, |
| 1882 | }; | 1843 | }; |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index d1f2ae1629f7..6dc156e1c29b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -2275,11 +2275,6 @@ fail: | |||
| 2275 | /* | 2275 | /* |
| 2276 | * sysfs parts below --> | 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 | static ssize_t | 2279 | static ssize_t |
| 2285 | cfq_var_show(unsigned int var, char *page) | 2280 | cfq_var_show(unsigned int var, char *page) |
| @@ -2297,8 +2292,9 @@ cfq_var_store(unsigned int *var, const char *page, size_t count) | |||
| 2297 | } | 2292 | } |
| 2298 | 2293 | ||
| 2299 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ | 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 | unsigned int __data = __VAR; \ | 2298 | unsigned int __data = __VAR; \ |
| 2303 | if (__CONV) \ | 2299 | if (__CONV) \ |
| 2304 | __data = jiffies_to_msecs(__data); \ | 2300 | __data = jiffies_to_msecs(__data); \ |
| @@ -2318,8 +2314,9 @@ SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); | |||
| 2318 | #undef SHOW_FUNCTION | 2314 | #undef SHOW_FUNCTION |
| 2319 | 2315 | ||
| 2320 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ | 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 | unsigned int __data; \ | 2320 | unsigned int __data; \ |
| 2324 | int ret = cfq_var_store(&__data, (page), count); \ | 2321 | int ret = cfq_var_store(&__data, (page), count); \ |
| 2325 | if (__data < (MIN)) \ | 2322 | if (__data < (MIN)) \ |
| @@ -2345,63 +2342,63 @@ STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, | |||
| 2345 | STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); | 2342 | STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); |
| 2346 | #undef STORE_FUNCTION | 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 | .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, | 2346 | .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, |
| 2350 | .show = cfq_quantum_show, | 2347 | .show = cfq_quantum_show, |
| 2351 | .store = cfq_quantum_store, | 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 | .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, | 2351 | .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, |
| 2355 | .show = cfq_queued_show, | 2352 | .show = cfq_queued_show, |
| 2356 | .store = cfq_queued_store, | 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 | .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, | 2356 | .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, |
| 2360 | .show = cfq_fifo_expire_sync_show, | 2357 | .show = cfq_fifo_expire_sync_show, |
| 2361 | .store = cfq_fifo_expire_sync_store, | 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 | .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, | 2361 | .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, |
| 2365 | .show = cfq_fifo_expire_async_show, | 2362 | .show = cfq_fifo_expire_async_show, |
| 2366 | .store = cfq_fifo_expire_async_store, | 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 | .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, | 2366 | .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, |
| 2370 | .show = cfq_back_max_show, | 2367 | .show = cfq_back_max_show, |
| 2371 | .store = cfq_back_max_store, | 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 | .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, | 2371 | .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, |
| 2375 | .show = cfq_back_penalty_show, | 2372 | .show = cfq_back_penalty_show, |
| 2376 | .store = cfq_back_penalty_store, | 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 | .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, | 2376 | .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, |
| 2380 | .show = cfq_slice_sync_show, | 2377 | .show = cfq_slice_sync_show, |
| 2381 | .store = cfq_slice_sync_store, | 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 | .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, | 2381 | .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, |
| 2385 | .show = cfq_slice_async_show, | 2382 | .show = cfq_slice_async_show, |
| 2386 | .store = cfq_slice_async_store, | 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 | .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, | 2386 | .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, |
| 2390 | .show = cfq_slice_async_rq_show, | 2387 | .show = cfq_slice_async_rq_show, |
| 2391 | .store = cfq_slice_async_rq_store, | 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 | .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, | 2391 | .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, |
| 2395 | .show = cfq_slice_idle_show, | 2392 | .show = cfq_slice_idle_show, |
| 2396 | .store = cfq_slice_idle_store, | 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 | .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, | 2396 | .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, |
| 2400 | .show = cfq_max_depth_show, | 2397 | .show = cfq_max_depth_show, |
| 2401 | .store = cfq_max_depth_store, | 2398 | .store = cfq_max_depth_store, |
| 2402 | }; | 2399 | }; |
| 2403 | 2400 | ||
| 2404 | static struct attribute *default_attrs[] = { | 2401 | static struct attribute *cfq_attrs[] = { |
| 2405 | &cfq_quantum_entry.attr, | 2402 | &cfq_quantum_entry.attr, |
| 2406 | &cfq_queued_entry.attr, | 2403 | &cfq_queued_entry.attr, |
| 2407 | &cfq_fifo_expire_sync_entry.attr, | 2404 | &cfq_fifo_expire_sync_entry.attr, |
| @@ -2416,43 +2413,6 @@ static struct attribute *default_attrs[] = { | |||
| 2416 | NULL, | 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 | static struct elevator_type iosched_cfq = { | 2416 | static struct elevator_type iosched_cfq = { |
| 2457 | .ops = { | 2417 | .ops = { |
| 2458 | .elevator_merge_fn = cfq_merge, | 2418 | .elevator_merge_fn = cfq_merge, |
| @@ -2473,7 +2433,7 @@ static struct elevator_type iosched_cfq = { | |||
| 2473 | .elevator_exit_fn = cfq_exit_queue, | 2433 | .elevator_exit_fn = cfq_exit_queue, |
| 2474 | .trim = cfq_trim, | 2434 | .trim = cfq_trim, |
| 2475 | }, | 2435 | }, |
| 2476 | .elevator_ktype = &cfq_ktype, | 2436 | .elevator_attrs = cfq_attrs, |
| 2477 | .elevator_name = "cfq", | 2437 | .elevator_name = "cfq", |
| 2478 | .elevator_owner = THIS_MODULE, | 2438 | .elevator_owner = THIS_MODULE, |
| 2479 | }; | 2439 | }; |
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 27e494b1bf97..a3e3ff1e0c65 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c | |||
| @@ -694,11 +694,6 @@ deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | |||
| 694 | /* | 694 | /* |
| 695 | * sysfs parts below | 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 | static ssize_t | 698 | static ssize_t |
| 704 | deadline_var_show(int var, char *page) | 699 | deadline_var_show(int var, char *page) |
| @@ -716,9 +711,10 @@ deadline_var_store(int *var, const char *page, size_t count) | |||
| 716 | } | 711 | } |
| 717 | 712 | ||
| 718 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ | 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 | if (__CONV) \ | 718 | if (__CONV) \ |
| 723 | __data = jiffies_to_msecs(__data); \ | 719 | __data = jiffies_to_msecs(__data); \ |
| 724 | return deadline_var_show(__data, (page)); \ | 720 | return deadline_var_show(__data, (page)); \ |
| @@ -731,8 +727,9 @@ SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0); | |||
| 731 | #undef SHOW_FUNCTION | 727 | #undef SHOW_FUNCTION |
| 732 | 728 | ||
| 733 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ | 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 | int __data; \ | 733 | int __data; \ |
| 737 | int ret = deadline_var_store(&__data, (page), count); \ | 734 | int ret = deadline_var_store(&__data, (page), count); \ |
| 738 | if (__data < (MIN)) \ | 735 | if (__data < (MIN)) \ |
| @@ -752,33 +749,33 @@ STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1, 0); | |||
| 752 | STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); | 749 | STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); |
| 753 | #undef STORE_FUNCTION | 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 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, | 753 | .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, |
| 757 | .show = deadline_readexpire_show, | 754 | .show = deadline_readexpire_show, |
| 758 | .store = deadline_readexpire_store, | 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 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, | 758 | .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, |
| 762 | .show = deadline_writeexpire_show, | 759 | .show = deadline_writeexpire_show, |
| 763 | .store = deadline_writeexpire_store, | 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 | .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR }, | 763 | .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR }, |
| 767 | .show = deadline_writesstarved_show, | 764 | .show = deadline_writesstarved_show, |
| 768 | .store = deadline_writesstarved_store, | 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 | .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR }, | 768 | .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR }, |
| 772 | .show = deadline_frontmerges_show, | 769 | .show = deadline_frontmerges_show, |
| 773 | .store = deadline_frontmerges_store, | 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 | .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR }, | 773 | .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR }, |
| 777 | .show = deadline_fifobatch_show, | 774 | .show = deadline_fifobatch_show, |
| 778 | .store = deadline_fifobatch_store, | 775 | .store = deadline_fifobatch_store, |
| 779 | }; | 776 | }; |
| 780 | 777 | ||
| 781 | static struct attribute *default_attrs[] = { | 778 | static struct attribute *deadline_attrs[] = { |
| 782 | &deadline_readexpire_entry.attr, | 779 | &deadline_readexpire_entry.attr, |
| 783 | &deadline_writeexpire_entry.attr, | 780 | &deadline_writeexpire_entry.attr, |
| 784 | &deadline_writesstarved_entry.attr, | 781 | &deadline_writesstarved_entry.attr, |
| @@ -787,43 +784,6 @@ static struct attribute *default_attrs[] = { | |||
| 787 | NULL, | 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 | static struct elevator_type iosched_deadline = { | 787 | static struct elevator_type iosched_deadline = { |
| 828 | .ops = { | 788 | .ops = { |
| 829 | .elevator_merge_fn = deadline_merge, | 789 | .elevator_merge_fn = deadline_merge, |
| @@ -840,7 +800,7 @@ static struct elevator_type iosched_deadline = { | |||
| 840 | .elevator_exit_fn = deadline_exit_queue, | 800 | .elevator_exit_fn = deadline_exit_queue, |
| 841 | }, | 801 | }, |
| 842 | 802 | ||
| 843 | .elevator_ktype = &deadline_ktype, | 803 | .elevator_attrs = deadline_attrs, |
| 844 | .elevator_name = "deadline", | 804 | .elevator_name = "deadline", |
| 845 | .elevator_owner = THIS_MODULE, | 805 | .elevator_owner = THIS_MODULE, |
| 846 | }; | 806 | }; |
diff --git a/block/elevator.c b/block/elevator.c index 0232df2b16e6..0d2db536c6a7 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -120,15 +120,10 @@ static struct elevator_type *elevator_get(const char *name) | |||
| 120 | return e; | 120 | return e; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static int elevator_attach(request_queue_t *q, struct elevator_type *e, | 123 | static int elevator_attach(request_queue_t *q, struct elevator_queue *eq) |
| 124 | struct elevator_queue *eq) | ||
| 125 | { | 124 | { |
| 126 | int ret = 0; | 125 | int ret = 0; |
| 127 | 126 | ||
| 128 | memset(eq, 0, sizeof(*eq)); | ||
| 129 | eq->ops = &e->ops; | ||
| 130 | eq->elevator_type = e; | ||
| 131 | |||
| 132 | q->elevator = eq; | 127 | q->elevator = eq; |
| 133 | 128 | ||
| 134 | if (eq->ops->elevator_init_fn) | 129 | if (eq->ops->elevator_init_fn) |
| @@ -154,6 +149,32 @@ static int __init elevator_setup(char *str) | |||
| 154 | 149 | ||
| 155 | __setup("elevator=", elevator_setup); | 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 | int elevator_init(request_queue_t *q, char *name) | 178 | int elevator_init(request_queue_t *q, char *name) |
| 158 | { | 179 | { |
| 159 | struct elevator_type *e = NULL; | 180 | struct elevator_type *e = NULL; |
| @@ -176,29 +197,26 @@ int elevator_init(request_queue_t *q, char *name) | |||
| 176 | e = elevator_get("noop"); | 197 | e = elevator_get("noop"); |
| 177 | } | 198 | } |
| 178 | 199 | ||
| 179 | eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); | 200 | eq = elevator_alloc(e); |
| 180 | if (!eq) { | 201 | if (!eq) |
| 181 | elevator_put(e); | ||
| 182 | return -ENOMEM; | 202 | return -ENOMEM; |
| 183 | } | ||
| 184 | 203 | ||
| 185 | ret = elevator_attach(q, e, eq); | 204 | ret = elevator_attach(q, eq); |
| 186 | if (ret) { | 205 | if (ret) |
| 187 | kfree(eq); | 206 | kobject_put(&eq->kobj); |
| 188 | elevator_put(e); | ||
| 189 | } | ||
| 190 | 207 | ||
| 191 | return ret; | 208 | return ret; |
| 192 | } | 209 | } |
| 193 | 210 | ||
| 194 | void elevator_exit(elevator_t *e) | 211 | void elevator_exit(elevator_t *e) |
| 195 | { | 212 | { |
| 213 | mutex_lock(&e->sysfs_lock); | ||
| 196 | if (e->ops->elevator_exit_fn) | 214 | if (e->ops->elevator_exit_fn) |
| 197 | e->ops->elevator_exit_fn(e); | 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); | 219 | kobject_put(&e->kobj); |
| 200 | e->elevator_type = NULL; | ||
| 201 | kfree(e); | ||
| 202 | } | 220 | } |
| 203 | 221 | ||
| 204 | /* | 222 | /* |
| @@ -627,26 +645,78 @@ void elv_completed_request(request_queue_t *q, struct request *rq) | |||
| 627 | } | 645 | } |
| 628 | } | 646 | } |
| 629 | 647 | ||
| 630 | int elv_register_queue(struct request_queue *q) | 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) | ||
| 631 | { | 652 | { |
| 632 | elevator_t *e = q->elevator; | 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 | } | ||
| 633 | 665 | ||
| 634 | e->kobj.parent = kobject_get(&q->kobj); | 666 | static ssize_t |
| 635 | if (!e->kobj.parent) | 667 | elv_attr_store(struct kobject *kobj, struct attribute *attr, |
| 636 | return -EBUSY; | 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; | ||
| 637 | 673 | ||
| 638 | snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); | 674 | if (!entry->store) |
| 639 | e->kobj.ktype = e->elevator_type->elevator_ktype; | 675 | return -EIO; |
| 640 | 676 | ||
| 641 | return kobject_register(&e->kobj); | 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 | |||
| 693 | int elv_register_queue(struct request_queue *q) | ||
| 694 | { | ||
| 695 | elevator_t *e = q->elevator; | ||
| 696 | int error; | ||
| 697 | |||
| 698 | e->kobj.parent = &q->kobj; | ||
| 699 | |||
| 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 | void elv_unregister_queue(struct request_queue *q) | 714 | void elv_unregister_queue(struct request_queue *q) |
| 645 | { | 715 | { |
| 646 | if (q) { | 716 | if (q) { |
| 647 | elevator_t *e = q->elevator; | 717 | elevator_t *e = q->elevator; |
| 648 | kobject_unregister(&e->kobj); | 718 | kobject_uevent(&e->kobj, KOBJ_REMOVE); |
| 649 | kobject_put(&q->kobj); | 719 | kobject_del(&e->kobj); |
| 650 | } | 720 | } |
| 651 | } | 721 | } |
| 652 | 722 | ||
| @@ -697,16 +767,16 @@ EXPORT_SYMBOL_GPL(elv_unregister); | |||
| 697 | * need for the new one. this way we have a chance of going back to the old | 767 | * need for the new one. this way we have a chance of going back to the old |
| 698 | * one, if the new one fails init for some reason. | 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 | elevator_t *old_elevator, *e; | 772 | elevator_t *old_elevator, *e; |
| 703 | 773 | ||
| 704 | /* | 774 | /* |
| 705 | * Allocate new elevator | 775 | * Allocate new elevator |
| 706 | */ | 776 | */ |
| 707 | e = kmalloc(sizeof(elevator_t), GFP_KERNEL); | 777 | e = elevator_alloc(new_e); |
| 708 | if (!e) | 778 | if (!e) |
| 709 | goto error; | 779 | return 0; |
| 710 | 780 | ||
| 711 | /* | 781 | /* |
| 712 | * Turn on BYPASS and drain all requests w/ elevator private data | 782 | * Turn on BYPASS and drain all requests w/ elevator private data |
| @@ -737,7 +807,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) | |||
| 737 | /* | 807 | /* |
| 738 | * attach and start new elevator | 808 | * attach and start new elevator |
| 739 | */ | 809 | */ |
| 740 | if (elevator_attach(q, new_e, e)) | 810 | if (elevator_attach(q, e)) |
| 741 | goto fail; | 811 | goto fail; |
| 742 | 812 | ||
| 743 | if (elv_register_queue(q)) | 813 | if (elv_register_queue(q)) |
| @@ -748,7 +818,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) | |||
| 748 | */ | 818 | */ |
| 749 | elevator_exit(old_elevator); | 819 | elevator_exit(old_elevator); |
| 750 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); | 820 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); |
| 751 | return; | 821 | return 1; |
| 752 | 822 | ||
| 753 | fail_register: | 823 | fail_register: |
| 754 | /* | 824 | /* |
| @@ -761,10 +831,9 @@ fail: | |||
| 761 | q->elevator = old_elevator; | 831 | q->elevator = old_elevator; |
| 762 | elv_register_queue(q); | 832 | elv_register_queue(q); |
| 763 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); | 833 | clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); |
| 764 | kfree(e); | 834 | if (e) |
| 765 | error: | 835 | kobject_put(&e->kobj); |
| 766 | elevator_put(new_e); | 836 | return 0; |
| 767 | printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); | ||
| 768 | } | 837 | } |
| 769 | 838 | ||
| 770 | ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) | 839 | ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) |
| @@ -791,7 +860,8 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) | |||
| 791 | return count; | 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 | return count; | 865 | return count; |
| 796 | } | 866 | } |
| 797 | 867 | ||
