aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/bitmap.c205
-rw-r--r--drivers/md/md.c5
-rw-r--r--drivers/md/md.h3
3 files changed, 211 insertions, 2 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 958865445f06..24fff75b2191 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -510,6 +510,9 @@ void bitmap_update_sb(struct bitmap *bitmap)
510 bitmap->events_cleared = bitmap->mddev->events; 510 bitmap->events_cleared = bitmap->mddev->events;
511 sb->events_cleared = cpu_to_le64(bitmap->events_cleared); 511 sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
512 } 512 }
513 /* Just in case these have been changed via sysfs: */
514 sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);
515 sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);
513 kunmap_atomic(sb, KM_USER0); 516 kunmap_atomic(sb, KM_USER0);
514 write_page(bitmap, bitmap->sb_page, 1); 517 write_page(bitmap, bitmap->sb_page, 1);
515} 518}
@@ -1714,6 +1717,208 @@ int bitmap_create(mddev_t *mddev)
1714 return err; 1717 return err;
1715} 1718}
1716 1719
1720static ssize_t
1721location_show(mddev_t *mddev, char *page)
1722{
1723 ssize_t len;
1724 if (mddev->bitmap_info.file) {
1725 len = sprintf(page, "file");
1726 } else if (mddev->bitmap_info.offset) {
1727 len = sprintf(page, "%+lld", (long long)mddev->bitmap_info.offset);
1728 } else
1729 len = sprintf(page, "none");
1730 len += sprintf(page+len, "\n");
1731 return len;
1732}
1733
1734static ssize_t
1735location_store(mddev_t *mddev, const char *buf, size_t len)
1736{
1737
1738 if (mddev->pers) {
1739 if (!mddev->pers->quiesce)
1740 return -EBUSY;
1741 if (mddev->recovery || mddev->sync_thread)
1742 return -EBUSY;
1743 }
1744
1745 if (mddev->bitmap || mddev->bitmap_info.file ||
1746 mddev->bitmap_info.offset) {
1747 /* bitmap already configured. Only option is to clear it */
1748 if (strncmp(buf, "none", 4) != 0)
1749 return -EBUSY;
1750 if (mddev->pers) {
1751 mddev->pers->quiesce(mddev, 1);
1752 bitmap_destroy(mddev);
1753 mddev->pers->quiesce(mddev, 0);
1754 }
1755 mddev->bitmap_info.offset = 0;
1756 if (mddev->bitmap_info.file) {
1757 struct file *f = mddev->bitmap_info.file;
1758 mddev->bitmap_info.file = NULL;
1759 restore_bitmap_write_access(f);
1760 fput(f);
1761 }
1762 } else {
1763 /* No bitmap, OK to set a location */
1764 long long offset;
1765 if (strncmp(buf, "none", 4) == 0)
1766 /* nothing to be done */;
1767 else if (strncmp(buf, "file:", 5) == 0) {
1768 /* Not supported yet */
1769 return -EINVAL;
1770 } else {
1771 int rv;
1772 if (buf[0] == '+')
1773 rv = strict_strtoll(buf+1, 10, &offset);
1774 else
1775 rv = strict_strtoll(buf, 10, &offset);
1776 if (rv)
1777 return rv;
1778 if (offset == 0)
1779 return -EINVAL;
1780 if (mddev->major_version == 0 &&
1781 offset != mddev->bitmap_info.default_offset)
1782 return -EINVAL;
1783 mddev->bitmap_info.offset = offset;
1784 if (mddev->pers) {
1785 mddev->pers->quiesce(mddev, 1);
1786 rv = bitmap_create(mddev);
1787 if (rv) {
1788 bitmap_destroy(mddev);
1789 mddev->bitmap_info.offset = 0;
1790 }
1791 mddev->pers->quiesce(mddev, 0);
1792 if (rv)
1793 return rv;
1794 }
1795 }
1796 }
1797 if (!mddev->external) {
1798 /* Ensure new bitmap info is stored in
1799 * metadata promptly.
1800 */
1801 set_bit(MD_CHANGE_DEVS, &mddev->flags);
1802 md_wakeup_thread(mddev->thread);
1803 }
1804 return len;
1805}
1806
1807static struct md_sysfs_entry bitmap_location =
1808__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
1809
1810static ssize_t
1811timeout_show(mddev_t *mddev, char *page)
1812{
1813 ssize_t len;
1814 unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ;
1815 unsigned long jifs = mddev->bitmap_info.daemon_sleep % HZ;
1816
1817 len = sprintf(page, "%lu", secs);
1818 if (jifs)
1819 len += sprintf(page+len, ".%03u", jiffies_to_msecs(jifs));
1820 len += sprintf(page+len, "\n");
1821 return len;
1822}
1823
1824static ssize_t
1825timeout_store(mddev_t *mddev, const char *buf, size_t len)
1826{
1827 /* timeout can be set at any time */
1828 unsigned long timeout;
1829 int rv = strict_strtoul_scaled(buf, &timeout, 4);
1830 if (rv)
1831 return rv;
1832
1833 /* just to make sure we don't overflow... */
1834 if (timeout >= LONG_MAX / HZ)
1835 return -EINVAL;
1836
1837 timeout = timeout * HZ / 10000;
1838
1839 if (timeout >= MAX_SCHEDULE_TIMEOUT)
1840 timeout = MAX_SCHEDULE_TIMEOUT-1;
1841 if (timeout < 1)
1842 timeout = 1;
1843 mddev->bitmap_info.daemon_sleep = timeout;
1844 if (mddev->thread) {
1845 /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then
1846 * the bitmap is all clean and we don't need to
1847 * adjust the timeout right now
1848 */
1849 if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) {
1850 mddev->thread->timeout = timeout;
1851 md_wakeup_thread(mddev->thread);
1852 }
1853 }
1854 return len;
1855}
1856
1857static struct md_sysfs_entry bitmap_timeout =
1858__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store);
1859
1860static ssize_t
1861backlog_show(mddev_t *mddev, char *page)
1862{
1863 return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind);
1864}
1865
1866static ssize_t
1867backlog_store(mddev_t *mddev, const char *buf, size_t len)
1868{
1869 unsigned long backlog;
1870 int rv = strict_strtoul(buf, 10, &backlog);
1871 if (rv)
1872 return rv;
1873 if (backlog > COUNTER_MAX)
1874 return -EINVAL;
1875 mddev->bitmap_info.max_write_behind = backlog;
1876 return len;
1877}
1878
1879static struct md_sysfs_entry bitmap_backlog =
1880__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store);
1881
1882static ssize_t
1883chunksize_show(mddev_t *mddev, char *page)
1884{
1885 return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize);
1886}
1887
1888static ssize_t
1889chunksize_store(mddev_t *mddev, const char *buf, size_t len)
1890{
1891 /* Can only be changed when no bitmap is active */
1892 int rv;
1893 unsigned long csize;
1894 if (mddev->bitmap)
1895 return -EBUSY;
1896 rv = strict_strtoul(buf, 10, &csize);
1897 if (rv)
1898 return rv;
1899 if (csize < 512 ||
1900 !is_power_of_2(csize))
1901 return -EINVAL;
1902 mddev->bitmap_info.chunksize = csize;
1903 return len;
1904}
1905
1906static struct md_sysfs_entry bitmap_chunksize =
1907__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
1908
1909static struct attribute *md_bitmap_attrs[] = {
1910 &bitmap_location.attr,
1911 &bitmap_timeout.attr,
1912 &bitmap_backlog.attr,
1913 &bitmap_chunksize.attr,
1914 NULL
1915};
1916struct attribute_group md_bitmap_group = {
1917 .name = "bitmap",
1918 .attrs = md_bitmap_attrs,
1919};
1920
1921
1717/* the bitmap API -- for raid personalities */ 1922/* the bitmap API -- for raid personalities */
1718EXPORT_SYMBOL(bitmap_startwrite); 1923EXPORT_SYMBOL(bitmap_startwrite);
1719EXPORT_SYMBOL(bitmap_endwrite); 1924EXPORT_SYMBOL(bitmap_endwrite);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 93287f88f1f4..859edbf8c9b0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4018,6 +4018,7 @@ static void mddev_delayed_delete(struct work_struct *ws)
4018 mddev->sysfs_action = NULL; 4018 mddev->sysfs_action = NULL;
4019 mddev->private = NULL; 4019 mddev->private = NULL;
4020 } 4020 }
4021 sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
4021 kobject_del(&mddev->kobj); 4022 kobject_del(&mddev->kobj);
4022 kobject_put(&mddev->kobj); 4023 kobject_put(&mddev->kobj);
4023} 4024}
@@ -4109,6 +4110,8 @@ static int md_alloc(dev_t dev, char *name)
4109 disk->disk_name); 4110 disk->disk_name);
4110 error = 0; 4111 error = 0;
4111 } 4112 }
4113 if (sysfs_create_group(&mddev->kobj, &md_bitmap_group))
4114 printk(KERN_DEBUG "pointless warning\n");
4112 abort: 4115 abort:
4113 mutex_unlock(&disks_mutex); 4116 mutex_unlock(&disks_mutex);
4114 if (!error) { 4117 if (!error) {
@@ -4434,7 +4437,7 @@ static int deny_bitmap_write_access(struct file * file)
4434 return 0; 4437 return 0;
4435} 4438}
4436 4439
4437static void restore_bitmap_write_access(struct file *file) 4440void restore_bitmap_write_access(struct file *file)
4438{ 4441{
4439 struct inode *inode = file->f_mapping->host; 4442 struct inode *inode = file->f_mapping->host;
4440 4443
diff --git a/drivers/md/md.h b/drivers/md/md.h
index b5c306925d94..fce02073f1a4 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -372,7 +372,7 @@ struct md_sysfs_entry {
372 ssize_t (*show)(mddev_t *, char *); 372 ssize_t (*show)(mddev_t *, char *);
373 ssize_t (*store)(mddev_t *, const char *, size_t); 373 ssize_t (*store)(mddev_t *, const char *, size_t);
374}; 374};
375 375extern struct attribute_group md_bitmap_group;
376 376
377static inline char * mdname (mddev_t * mddev) 377static inline char * mdname (mddev_t * mddev)
378{ 378{
@@ -465,5 +465,6 @@ extern int md_check_no_bitmap(mddev_t *mddev);
465extern int md_integrity_register(mddev_t *mddev); 465extern int md_integrity_register(mddev_t *mddev);
466extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev); 466extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
467extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale); 467extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
468extern void restore_bitmap_write_access(struct file *file);
468 469
469#endif /* _MD_MD_H */ 470#endif /* _MD_MD_H */