aboutsummaryrefslogtreecommitdiffstats
path: root/block/as-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/as-iosched.c')
-rw-r--r--block/as-iosched.c144
1 files changed, 49 insertions, 95 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 8da3cf66894c..296708ceceb2 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -182,6 +182,9 @@ struct as_rq {
182 182
183static kmem_cache_t *arq_pool; 183static kmem_cache_t *arq_pool;
184 184
185static atomic_t ioc_count = ATOMIC_INIT(0);
186static struct completion *ioc_gone;
187
185static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); 188static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
186static void as_antic_stop(struct as_data *ad); 189static void as_antic_stop(struct as_data *ad);
187 190
@@ -193,6 +196,15 @@ static void as_antic_stop(struct as_data *ad);
193static void free_as_io_context(struct as_io_context *aic) 196static void free_as_io_context(struct as_io_context *aic)
194{ 197{
195 kfree(aic); 198 kfree(aic);
199 if (atomic_dec_and_test(&ioc_count) && ioc_gone)
200 complete(ioc_gone);
201}
202
203static void as_trim(struct io_context *ioc)
204{
205 if (ioc->aic)
206 free_as_io_context(ioc->aic);
207 ioc->aic = NULL;
196} 208}
197 209
198/* Called when the task exits */ 210/* Called when the task exits */
@@ -220,6 +232,7 @@ static struct as_io_context *alloc_as_io_context(void)
220 ret->seek_total = 0; 232 ret->seek_total = 0;
221 ret->seek_samples = 0; 233 ret->seek_samples = 0;
222 ret->seek_mean = 0; 234 ret->seek_mean = 0;
235 atomic_inc(&ioc_count);
223 } 236 }
224 237
225 return ret; 238 return ret;
@@ -1696,11 +1709,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
1696/* 1709/*
1697 * sysfs parts below 1710 * sysfs parts below
1698 */ 1711 */
1699struct as_fs_entry {
1700 struct attribute attr;
1701 ssize_t (*show)(struct as_data *, char *);
1702 ssize_t (*store)(struct as_data *, const char *, size_t);
1703};
1704 1712
1705static ssize_t 1713static ssize_t
1706as_var_show(unsigned int var, char *page) 1714as_var_show(unsigned int var, char *page)
@@ -1717,8 +1725,9 @@ as_var_store(unsigned long *var, const char *page, size_t count)
1717 return count; 1725 return count;
1718} 1726}
1719 1727
1720static ssize_t as_est_show(struct as_data *ad, char *page) 1728static ssize_t est_time_show(elevator_t *e, char *page)
1721{ 1729{
1730 struct as_data *ad = e->elevator_data;
1722 int pos = 0; 1731 int pos = 0;
1723 1732
1724 pos += sprintf(page+pos, "%lu %% exit probability\n", 1733 pos += sprintf(page+pos, "%lu %% exit probability\n",
@@ -1734,21 +1743,23 @@ static ssize_t as_est_show(struct as_data *ad, char *page)
1734} 1743}
1735 1744
1736#define SHOW_FUNCTION(__FUNC, __VAR) \ 1745#define SHOW_FUNCTION(__FUNC, __VAR) \
1737static ssize_t __FUNC(struct as_data *ad, char *page) \ 1746static ssize_t __FUNC(elevator_t *e, char *page) \
1738{ \ 1747{ \
1748 struct as_data *ad = e->elevator_data; \
1739 return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ 1749 return as_var_show(jiffies_to_msecs((__VAR)), (page)); \
1740} 1750}
1741SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); 1751SHOW_FUNCTION(as_read_expire_show, ad->fifo_expire[REQ_SYNC]);
1742SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]); 1752SHOW_FUNCTION(as_write_expire_show, ad->fifo_expire[REQ_ASYNC]);
1743SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire); 1753SHOW_FUNCTION(as_antic_expire_show, ad->antic_expire);
1744SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]); 1754SHOW_FUNCTION(as_read_batch_expire_show, ad->batch_expire[REQ_SYNC]);
1745SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]); 1755SHOW_FUNCTION(as_write_batch_expire_show, ad->batch_expire[REQ_ASYNC]);
1746#undef SHOW_FUNCTION 1756#undef SHOW_FUNCTION
1747 1757
1748#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ 1758#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
1749static 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) \
1750{ \ 1760{ \
1751 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); \
1752 if (*(__PTR) < (MIN)) \ 1763 if (*(__PTR) < (MIN)) \
1753 *(__PTR) = (MIN); \ 1764 *(__PTR) = (MIN); \
1754 else if (*(__PTR) > (MAX)) \ 1765 else if (*(__PTR) > (MAX)) \
@@ -1756,90 +1767,26 @@ static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \
1756 *(__PTR) = msecs_to_jiffies(*(__PTR)); \ 1767 *(__PTR) = msecs_to_jiffies(*(__PTR)); \
1757 return ret; \ 1768 return ret; \
1758} 1769}
1759STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX); 1770STORE_FUNCTION(as_read_expire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
1760STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX); 1771STORE_FUNCTION(as_write_expire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
1761STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX); 1772STORE_FUNCTION(as_antic_expire_store, &ad->antic_expire, 0, INT_MAX);
1762STORE_FUNCTION(as_read_batchexpire_store, 1773STORE_FUNCTION(as_read_batch_expire_store,
1763 &ad->batch_expire[REQ_SYNC], 0, INT_MAX); 1774 &ad->batch_expire[REQ_SYNC], 0, INT_MAX);
1764STORE_FUNCTION(as_write_batchexpire_store, 1775STORE_FUNCTION(as_write_batch_expire_store,
1765 &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); 1776 &ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
1766#undef STORE_FUNCTION 1777#undef STORE_FUNCTION
1767 1778
1768static struct as_fs_entry as_est_entry = { 1779#define AS_ATTR(name) \
1769 .attr = {.name = "est_time", .mode = S_IRUGO }, 1780 __ATTR(name, S_IRUGO|S_IWUSR, as_##name##_show, as_##name##_store)
1770 .show = as_est_show, 1781
1771}; 1782static struct elv_fs_entry as_attrs[] = {
1772static struct as_fs_entry as_readexpire_entry = { 1783 __ATTR_RO(est_time),
1773 .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, 1784 AS_ATTR(read_expire),
1774 .show = as_readexpire_show, 1785 AS_ATTR(write_expire),
1775 .store = as_readexpire_store, 1786 AS_ATTR(antic_expire),
1776}; 1787 AS_ATTR(read_batch_expire),
1777static struct as_fs_entry as_writeexpire_entry = { 1788 AS_ATTR(write_batch_expire),
1778 .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, 1789 __ATTR_NULL
1779 .show = as_writeexpire_show,
1780 .store = as_writeexpire_store,
1781};
1782static struct as_fs_entry as_anticexpire_entry = {
1783 .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR },
1784 .show = as_anticexpire_show,
1785 .store = as_anticexpire_store,
1786};
1787static struct as_fs_entry as_read_batchexpire_entry = {
1788 .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR },
1789 .show = as_read_batchexpire_show,
1790 .store = as_read_batchexpire_store,
1791};
1792static struct as_fs_entry as_write_batchexpire_entry = {
1793 .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR },
1794 .show = as_write_batchexpire_show,
1795 .store = as_write_batchexpire_store,
1796};
1797
1798static struct attribute *default_attrs[] = {
1799 &as_est_entry.attr,
1800 &as_readexpire_entry.attr,
1801 &as_writeexpire_entry.attr,
1802 &as_anticexpire_entry.attr,
1803 &as_read_batchexpire_entry.attr,
1804 &as_write_batchexpire_entry.attr,
1805 NULL,
1806};
1807
1808#define to_as(atr) container_of((atr), struct as_fs_entry, attr)
1809
1810static ssize_t
1811as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
1812{
1813 elevator_t *e = container_of(kobj, elevator_t, kobj);
1814 struct as_fs_entry *entry = to_as(attr);
1815
1816 if (!entry->show)
1817 return -EIO;
1818
1819 return entry->show(e->elevator_data, page);
1820}
1821
1822static ssize_t
1823as_attr_store(struct kobject *kobj, struct attribute *attr,
1824 const char *page, size_t length)
1825{
1826 elevator_t *e = container_of(kobj, elevator_t, kobj);
1827 struct as_fs_entry *entry = to_as(attr);
1828
1829 if (!entry->store)
1830 return -EIO;
1831
1832 return entry->store(e->elevator_data, page, length);
1833}
1834
1835static struct sysfs_ops as_sysfs_ops = {
1836 .show = as_attr_show,
1837 .store = as_attr_store,
1838};
1839
1840static struct kobj_type as_ktype = {
1841 .sysfs_ops = &as_sysfs_ops,
1842 .default_attrs = default_attrs,
1843}; 1790};
1844 1791
1845static struct elevator_type iosched_as = { 1792static struct elevator_type iosched_as = {
@@ -1860,9 +1807,10 @@ static struct elevator_type iosched_as = {
1860 .elevator_may_queue_fn = as_may_queue, 1807 .elevator_may_queue_fn = as_may_queue,
1861 .elevator_init_fn = as_init_queue, 1808 .elevator_init_fn = as_init_queue,
1862 .elevator_exit_fn = as_exit_queue, 1809 .elevator_exit_fn = as_exit_queue,
1810 .trim = as_trim,
1863 }, 1811 },
1864 1812
1865 .elevator_ktype = &as_ktype, 1813 .elevator_attrs = as_attrs,
1866 .elevator_name = "anticipatory", 1814 .elevator_name = "anticipatory",
1867 .elevator_owner = THIS_MODULE, 1815 .elevator_owner = THIS_MODULE,
1868}; 1816};
@@ -1893,7 +1841,13 @@ static int __init as_init(void)
1893 1841
1894static void __exit as_exit(void) 1842static void __exit as_exit(void)
1895{ 1843{
1844 DECLARE_COMPLETION(all_gone);
1896 elv_unregister(&iosched_as); 1845 elv_unregister(&iosched_as);
1846 ioc_gone = &all_gone;
1847 barrier();
1848 if (atomic_read(&ioc_count))
1849 complete(ioc_gone);
1850 synchronize_rcu();
1897 kmem_cache_destroy(arq_pool); 1851 kmem_cache_destroy(arq_pool);
1898} 1852}
1899 1853