aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-03-18 18:35:43 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2006-03-18 18:35:43 -0500
commit3d1ab40f4c20767afbd361b258a531d73e3e6fc2 (patch)
tree2da79cc8b47a98b0496b6e762fa790a8d547977b
parent1cc9be68ebcc1de9904bf225441613878da9c0d8 (diff)
[PATCH] elevator_t lifetime rules and sysfs fixes
-rw-r--r--block/as-iosched.c69
-rw-r--r--block/cfq-iosched.c74
-rw-r--r--block/deadline-iosched.c64
-rw-r--r--block/elevator.c146
-rw-r--r--include/linux/elevator.h9
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 */
1712struct 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
1718static ssize_t 1713static ssize_t
1719as_var_show(unsigned int var, char *page) 1714as_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
1733static ssize_t as_est_show(struct as_data *ad, char *page) 1728static 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) \
1750static ssize_t __FUNC(struct as_data *ad, char *page) \ 1746static 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}
1754SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); 1751SHOW_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) \
1762static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \ 1759static 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
1781static struct as_fs_entry as_est_entry = { 1779static 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};
1785static struct as_fs_entry as_readexpire_entry = { 1783static 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};
1790static struct as_fs_entry as_writeexpire_entry = { 1788static 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};
1795static struct as_fs_entry as_anticexpire_entry = { 1793static 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};
1800static struct as_fs_entry as_read_batchexpire_entry = { 1798static 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};
1805static struct as_fs_entry as_write_batchexpire_entry = { 1803static 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
1811static struct attribute *default_attrs[] = { 1809static 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
1823static ssize_t
1824as_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
1835static ssize_t
1836as_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
1848static struct sysfs_ops as_sysfs_ops = {
1849 .show = as_attr_show,
1850 .store = as_attr_store,
1851};
1852
1853static struct kobj_type as_ktype = {
1854 .sysfs_ops = &as_sysfs_ops,
1855 .default_attrs = default_attrs,
1856};
1857
1858static struct elevator_type iosched_as = { 1819static 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 */
2278struct 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
2284static ssize_t 2279static ssize_t
2285cfq_var_show(unsigned int var, char *page) 2280cfq_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) \
2300static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ 2295static 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) \
2321static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ 2317static 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,
2345STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); 2342STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
2346#undef STORE_FUNCTION 2343#undef STORE_FUNCTION
2347 2344
2348static struct cfq_fs_entry cfq_quantum_entry = { 2345static 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};
2353static struct cfq_fs_entry cfq_queued_entry = { 2350static 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};
2358static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { 2355static 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};
2363static struct cfq_fs_entry cfq_fifo_expire_async_entry = { 2360static 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};
2368static struct cfq_fs_entry cfq_back_max_entry = { 2365static 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};
2373static struct cfq_fs_entry cfq_back_penalty_entry = { 2370static 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};
2378static struct cfq_fs_entry cfq_slice_sync_entry = { 2375static 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};
2383static struct cfq_fs_entry cfq_slice_async_entry = { 2380static 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};
2388static struct cfq_fs_entry cfq_slice_async_rq_entry = { 2385static 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};
2393static struct cfq_fs_entry cfq_slice_idle_entry = { 2390static 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};
2398static struct cfq_fs_entry cfq_max_depth_entry = { 2395static 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
2404static struct attribute *default_attrs[] = { 2401static 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
2421static ssize_t
2422cfq_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
2433static ssize_t
2434cfq_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
2446static struct sysfs_ops cfq_sysfs_ops = {
2447 .show = cfq_attr_show,
2448 .store = cfq_attr_store,
2449};
2450
2451static struct kobj_type cfq_ktype = {
2452 .sysfs_ops = &cfq_sysfs_ops,
2453 .default_attrs = default_attrs,
2454};
2455
2456static struct elevator_type iosched_cfq = { 2416static 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 */
697struct 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
703static ssize_t 698static ssize_t
704deadline_var_show(int var, char *page) 699deadline_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) \
719static ssize_t __FUNC(struct deadline_data *dd, char *page) \ 714static 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) \
734static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \ 730static 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);
752STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); 749STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0);
753#undef STORE_FUNCTION 750#undef STORE_FUNCTION
754 751
755static struct deadline_fs_entry deadline_readexpire_entry = { 752static 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};
760static struct deadline_fs_entry deadline_writeexpire_entry = { 757static 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};
765static struct deadline_fs_entry deadline_writesstarved_entry = { 762static 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};
770static struct deadline_fs_entry deadline_frontmerges_entry = { 767static 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};
775static struct deadline_fs_entry deadline_fifobatch_entry = { 772static 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
781static struct attribute *default_attrs[] = { 778static 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
792static ssize_t
793deadline_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
804static ssize_t
805deadline_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
817static struct sysfs_ops deadline_sysfs_ops = {
818 .show = deadline_attr_show,
819 .store = deadline_attr_store,
820};
821
822static struct kobj_type deadline_ktype = {
823 .sysfs_ops = &deadline_sysfs_ops,
824 .default_attrs = default_attrs,
825};
826
827static struct elevator_type iosched_deadline = { 787static 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
123static int elevator_attach(request_queue_t *q, struct elevator_type *e, 123static 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
152static struct kobj_type elv_ktype;
153
154static 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
171static 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
157int elevator_init(request_queue_t *q, char *name) 178int 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
194void elevator_exit(elevator_t *e) 211void 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
630int elv_register_queue(struct request_queue *q) 648#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
649
650static ssize_t
651elv_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); 666static ssize_t
635 if (!e->kobj.parent) 667elv_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
683static struct sysfs_ops elv_sysfs_ops = {
684 .show = elv_attr_show,
685 .store = elv_attr_store,
686};
687
688static struct kobj_type elv_ktype = {
689 .sysfs_ops = &elv_sysfs_ops,
690 .release = elevator_release,
691};
692
693int 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
644void elv_unregister_queue(struct request_queue *q) 714void 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 */
700static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) 770static 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
753fail_register: 823fail_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)
765error: 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
770ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) 839ssize_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
145struct 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