diff options
-rw-r--r-- | drivers/md/bitmap.c | 39 | ||||
-rw-r--r-- | drivers/md/md.c | 33 | ||||
-rw-r--r-- | drivers/md/md.h | 3 |
3 files changed, 73 insertions, 2 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c7784a985676..ac688fb54e1d 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -1934,6 +1934,44 @@ location_store(struct mddev *mddev, const char *buf, size_t len) | |||
1934 | static struct md_sysfs_entry bitmap_location = | 1934 | static struct md_sysfs_entry bitmap_location = |
1935 | __ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); | 1935 | __ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); |
1936 | 1936 | ||
1937 | /* 'bitmap/space' is the space available at 'location' for the | ||
1938 | * bitmap. This allows the kernel to know when it is safe to | ||
1939 | * resize the bitmap to match a resized array. | ||
1940 | */ | ||
1941 | static ssize_t | ||
1942 | space_show(struct mddev *mddev, char *page) | ||
1943 | { | ||
1944 | return sprintf(page, "%lu\n", mddev->bitmap_info.space); | ||
1945 | } | ||
1946 | |||
1947 | static ssize_t | ||
1948 | space_store(struct mddev *mddev, const char *buf, size_t len) | ||
1949 | { | ||
1950 | unsigned long sectors; | ||
1951 | int rv; | ||
1952 | |||
1953 | rv = kstrtoul(buf, 10, §ors); | ||
1954 | if (rv) | ||
1955 | return rv; | ||
1956 | |||
1957 | if (sectors == 0) | ||
1958 | return -EINVAL; | ||
1959 | |||
1960 | if (mddev->bitmap && | ||
1961 | sectors < ((mddev->bitmap->file_pages - 1) * PAGE_SIZE | ||
1962 | + mddev->bitmap->last_page_size + 511) >> 9) | ||
1963 | return -EFBIG; /* Bitmap is too big for this small space */ | ||
1964 | |||
1965 | /* could make sure it isn't too big, but that isn't really | ||
1966 | * needed - user-space should be careful. | ||
1967 | */ | ||
1968 | mddev->bitmap_info.space = sectors; | ||
1969 | return len; | ||
1970 | } | ||
1971 | |||
1972 | static struct md_sysfs_entry bitmap_space = | ||
1973 | __ATTR(space, S_IRUGO|S_IWUSR, space_show, space_store); | ||
1974 | |||
1937 | static ssize_t | 1975 | static ssize_t |
1938 | timeout_show(struct mddev *mddev, char *page) | 1976 | timeout_show(struct mddev *mddev, char *page) |
1939 | { | 1977 | { |
@@ -2109,6 +2147,7 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR, | |||
2109 | 2147 | ||
2110 | static struct attribute *md_bitmap_attrs[] = { | 2148 | static struct attribute *md_bitmap_attrs[] = { |
2111 | &bitmap_location.attr, | 2149 | &bitmap_location.attr, |
2150 | &bitmap_space.attr, | ||
2112 | &bitmap_timeout.attr, | 2151 | &bitmap_timeout.attr, |
2113 | &bitmap_backlog.attr, | 2152 | &bitmap_backlog.attr, |
2114 | &bitmap_chunksize.attr, | 2153 | &bitmap_chunksize.attr, |
diff --git a/drivers/md/md.c b/drivers/md/md.c index ac99616f48d4..9a677f2078a7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1197,7 +1197,10 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1197 | mddev->dev_sectors = ((sector_t)sb->size) * 2; | 1197 | mddev->dev_sectors = ((sector_t)sb->size) * 2; |
1198 | mddev->events = ev1; | 1198 | mddev->events = ev1; |
1199 | mddev->bitmap_info.offset = 0; | 1199 | mddev->bitmap_info.offset = 0; |
1200 | mddev->bitmap_info.space = 0; | ||
1201 | /* bitmap can use 60 K after the 4K superblocks */ | ||
1200 | mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; | 1202 | mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; |
1203 | mddev->bitmap_info.default_space = 64*2 - (MD_SB_BYTES >> 9); | ||
1201 | mddev->reshape_backwards = 0; | 1204 | mddev->reshape_backwards = 0; |
1202 | 1205 | ||
1203 | if (mddev->minor_version >= 91) { | 1206 | if (mddev->minor_version >= 91) { |
@@ -1234,9 +1237,12 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1234 | mddev->max_disks = MD_SB_DISKS; | 1237 | mddev->max_disks = MD_SB_DISKS; |
1235 | 1238 | ||
1236 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && | 1239 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && |
1237 | mddev->bitmap_info.file == NULL) | 1240 | mddev->bitmap_info.file == NULL) { |
1238 | mddev->bitmap_info.offset = | 1241 | mddev->bitmap_info.offset = |
1239 | mddev->bitmap_info.default_offset; | 1242 | mddev->bitmap_info.default_offset; |
1243 | mddev->bitmap_info.space = | ||
1244 | mddev->bitmap_info.space; | ||
1245 | } | ||
1240 | 1246 | ||
1241 | } else if (mddev->pers == NULL) { | 1247 | } else if (mddev->pers == NULL) { |
1242 | /* Insist on good event counter while assembling, except | 1248 | /* Insist on good event counter while assembling, except |
@@ -1677,7 +1683,12 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1677 | mddev->dev_sectors = le64_to_cpu(sb->size); | 1683 | mddev->dev_sectors = le64_to_cpu(sb->size); |
1678 | mddev->events = ev1; | 1684 | mddev->events = ev1; |
1679 | mddev->bitmap_info.offset = 0; | 1685 | mddev->bitmap_info.offset = 0; |
1686 | mddev->bitmap_info.space = 0; | ||
1687 | /* Default location for bitmap is 1K after superblock | ||
1688 | * using 3K - total of 4K | ||
1689 | */ | ||
1680 | mddev->bitmap_info.default_offset = 1024 >> 9; | 1690 | mddev->bitmap_info.default_offset = 1024 >> 9; |
1691 | mddev->bitmap_info.default_space = (4096-1024) >> 9; | ||
1681 | mddev->reshape_backwards = 0; | 1692 | mddev->reshape_backwards = 0; |
1682 | 1693 | ||
1683 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); | 1694 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); |
@@ -1686,9 +1697,23 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1686 | mddev->max_disks = (4096-256)/2; | 1697 | mddev->max_disks = (4096-256)/2; |
1687 | 1698 | ||
1688 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && | 1699 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && |
1689 | mddev->bitmap_info.file == NULL ) | 1700 | mddev->bitmap_info.file == NULL) { |
1690 | mddev->bitmap_info.offset = | 1701 | mddev->bitmap_info.offset = |
1691 | (__s32)le32_to_cpu(sb->bitmap_offset); | 1702 | (__s32)le32_to_cpu(sb->bitmap_offset); |
1703 | /* Metadata doesn't record how much space is available. | ||
1704 | * For 1.0, we assume we can use up to the superblock | ||
1705 | * if before, else to 4K beyond superblock. | ||
1706 | * For others, assume no change is possible. | ||
1707 | */ | ||
1708 | if (mddev->minor_version > 0) | ||
1709 | mddev->bitmap_info.space = 0; | ||
1710 | else if (mddev->bitmap_info.offset > 0) | ||
1711 | mddev->bitmap_info.space = | ||
1712 | 8 - mddev->bitmap_info.offset; | ||
1713 | else | ||
1714 | mddev->bitmap_info.space = | ||
1715 | -mddev->bitmap_info.offset; | ||
1716 | } | ||
1692 | 1717 | ||
1693 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { | 1718 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { |
1694 | mddev->reshape_position = le64_to_cpu(sb->reshape_position); | 1719 | mddev->reshape_position = le64_to_cpu(sb->reshape_position); |
@@ -5280,6 +5305,7 @@ static void md_clean(struct mddev *mddev) | |||
5280 | mddev->merge_check_needed = 0; | 5305 | mddev->merge_check_needed = 0; |
5281 | mddev->bitmap_info.offset = 0; | 5306 | mddev->bitmap_info.offset = 0; |
5282 | mddev->bitmap_info.default_offset = 0; | 5307 | mddev->bitmap_info.default_offset = 0; |
5308 | mddev->bitmap_info.default_space = 0; | ||
5283 | mddev->bitmap_info.chunksize = 0; | 5309 | mddev->bitmap_info.chunksize = 0; |
5284 | mddev->bitmap_info.daemon_sleep = 0; | 5310 | mddev->bitmap_info.daemon_sleep = 0; |
5285 | mddev->bitmap_info.max_write_behind = 0; | 5311 | mddev->bitmap_info.max_write_behind = 0; |
@@ -6076,6 +6102,7 @@ static int set_array_info(struct mddev * mddev, mdu_array_info_t *info) | |||
6076 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 6102 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
6077 | 6103 | ||
6078 | mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; | 6104 | mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; |
6105 | mddev->bitmap_info.default_space = 64*2 - (MD_SB_BYTES >> 9); | ||
6079 | mddev->bitmap_info.offset = 0; | 6106 | mddev->bitmap_info.offset = 0; |
6080 | 6107 | ||
6081 | mddev->reshape_position = MaxSector; | 6108 | mddev->reshape_position = MaxSector; |
@@ -6258,6 +6285,8 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) | |||
6258 | return -EINVAL; | 6285 | return -EINVAL; |
6259 | mddev->bitmap_info.offset = | 6286 | mddev->bitmap_info.offset = |
6260 | mddev->bitmap_info.default_offset; | 6287 | mddev->bitmap_info.default_offset; |
6288 | mddev->bitmap_info.space = | ||
6289 | mddev->bitmap_info.default_space; | ||
6261 | mddev->pers->quiesce(mddev, 1); | 6290 | mddev->pers->quiesce(mddev, 1); |
6262 | rv = bitmap_create(mddev); | 6291 | rv = bitmap_create(mddev); |
6263 | if (!rv) | 6292 | if (!rv) |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 360937389e64..7b4a3c318cae 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -393,10 +393,13 @@ struct mddev { | |||
393 | * For external metadata, offset | 393 | * For external metadata, offset |
394 | * from start of device. | 394 | * from start of device. |
395 | */ | 395 | */ |
396 | unsigned long space; /* space available at this offset */ | ||
396 | loff_t default_offset; /* this is the offset to use when | 397 | loff_t default_offset; /* this is the offset to use when |
397 | * hot-adding a bitmap. It should | 398 | * hot-adding a bitmap. It should |
398 | * eventually be settable by sysfs. | 399 | * eventually be settable by sysfs. |
399 | */ | 400 | */ |
401 | unsigned long default_space; /* space available at | ||
402 | * default offset */ | ||
400 | struct mutex mutex; | 403 | struct mutex mutex; |
401 | unsigned long chunksize; | 404 | unsigned long chunksize; |
402 | unsigned long daemon_sleep; /* how many jiffies between updates? */ | 405 | unsigned long daemon_sleep; /* how many jiffies between updates? */ |