diff options
-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 | ||||
-rw-r--r-- | include/linux/elevator.h | 9 |
5 files changed, 160 insertions, 202 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 | ||
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index f65766ef0532..4d0a80f13ee0 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
@@ -61,7 +61,7 @@ struct elevator_type | |||
61 | struct list_head list; | 61 | struct list_head list; |
62 | struct elevator_ops ops; | 62 | struct elevator_ops ops; |
63 | struct elevator_type *elevator_type; | 63 | struct elevator_type *elevator_type; |
64 | struct kobj_type *elevator_ktype; | 64 | struct attribute **elevator_attrs; |
65 | char elevator_name[ELV_NAME_MAX]; | 65 | char elevator_name[ELV_NAME_MAX]; |
66 | struct module *elevator_owner; | 66 | struct module *elevator_owner; |
67 | }; | 67 | }; |
@@ -75,6 +75,7 @@ struct elevator_queue | |||
75 | void *elevator_data; | 75 | void *elevator_data; |
76 | struct kobject kobj; | 76 | struct kobject kobj; |
77 | struct elevator_type *elevator_type; | 77 | struct elevator_type *elevator_type; |
78 | struct mutex sysfs_lock; | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | /* | 81 | /* |
@@ -141,6 +142,12 @@ enum { | |||
141 | ELV_MQUEUE_MUST, | 142 | ELV_MQUEUE_MUST, |
142 | }; | 143 | }; |
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); | ||
149 | }; | ||
150 | |||
144 | #define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) | 151 | #define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) |
145 | 152 | ||
146 | #endif | 153 | #endif |