aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-12-13 20:49:55 -0500
committerNeilBrown <neilb@suse.de>2009-12-13 20:51:41 -0500
commit43a705076e51c5af21ec4260a35699775ea298f5 (patch)
treeff8e161d841c41992dbbcca2a844816411941c3c
parent72e02075a33f739e21430262f71da8e82db9dbb3 (diff)
md: support updating bitmap parameters via sysfs.
A new attribute directory 'bitmap' in 'md' is created which contains files for configuring the bitmap. 'location' identifies where the bitmap is, either 'none', or 'file' or 'sector offset from metadata'. Writing 'location' can create or remove a bitmap. Adding a 'file' bitmap this way is not yet supported. 'chunksize' and 'time_base' must be set before 'location' can be set. 'chunksize' can be set before creating a bitmap, but is currently always over-ridden by the bitmap superblock. 'time_base' and 'backlog' can be updated at any time. Signed-off-by: NeilBrown <neilb@suse.de> Reviewed-by: Andre Noll <maan@systemlinux.org>
-rw-r--r--Documentation/md.txt29
-rw-r--r--drivers/md/bitmap.c205
-rw-r--r--drivers/md/md.c5
-rw-r--r--drivers/md/md.h3
4 files changed, 240 insertions, 2 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 4edd39ec7db9..18fad6876228 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -296,6 +296,35 @@ All md devices contain:
296 active-idle 296 active-idle
297 like active, but no writes have been seen for a while (safe_mode_delay). 297 like active, but no writes have been seen for a while (safe_mode_delay).
298 298
299 bitmap/location
300 This indicates where the write-intent bitmap for the array is
301 stored.
302 It can be one of "none", "file" or "[+-]N".
303 "file" may later be extended to "file:/file/name"
304 "[+-]N" means that many sectors from the start of the metadata.
305 This is replicated on all devices. For arrays with externally
306 managed metadata, the offset is from the beginning of the
307 device.
308 bitmap/chunksize
309 The size, in bytes, of the chunk which will be represented by a
310 single bit. For RAID456, it is a portion of an individual
311 device. For RAID10, it is a portion of the array. For RAID1, it
312 is both (they come to the same thing).
313 bitmap/time_base
314 The time, in seconds, between looking for bits in the bitmap to
315 be cleared. In the current implementation, a bit will be cleared
316 between 2 and 3 times "time_base" after all the covered blocks
317 are known to be in-sync.
318 bitmap/backlog
319 When write-mostly devices are active in a RAID1, write requests
320 to those devices proceed in the background - the filesystem (or
321 other user of the device) does not have to wait for them.
322 'backlog' sets a limit on the number of concurrent background
323 writes. If there are more than this, new writes will by
324 synchronous.
325
326
327
299 328
300As component devices are added to an md array, they appear in the 'md' 329As component devices are added to an md array, they appear in the 'md'
301directory as new directories named 330directory as new directories named
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 */