Commit 3d1ab40f4c20767afbd361b258a531d73e3e6fc2

Authored by Al Viro
1 parent 1cc9be68eb

[PATCH] elevator_t lifetime rules and sysfs fixes

Showing 5 changed files with 160 additions and 202 deletions Side-by-side Diff

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