You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md: (24 commits) md: clean up do_md_stop md: fix another deadlock with removing sysfs attributes. md: move revalidate_disk() back outside open_mutex md/raid10: fix deadlock with unaligned read during resync md/bitmap: separate out loading a bitmap from initialising the structures. md/bitmap: prepare for storing write-intent-bitmap via dm-dirty-log. md/bitmap: optimise scanning of empty bitmaps. md/bitmap: clean up plugging calls. md/bitmap: reduce dependence on sysfs. md/bitmap: white space clean up and similar. md/raid5: export raid5 unplugging interface. md/plug: optionally use plugger to unplug an array during resync/recovery. md/raid5: add simple plugging infrastructure. md/raid5: export is_congested test raid5: Don't set read-ahead when there is no queue md: add support for raising dm events. md: export various start/stop interfaces md: split out md_rdev_init md: be more careful setting MD_CHANGE_CLEAN md/raid5: ensure we create a unique name for kmem_cache when mddev has no gendisk ...
This commit is contained in:
@@ -22,6 +22,20 @@ config ASYNC_RAID6_RECOV
|
||||
tristate
|
||||
select ASYNC_CORE
|
||||
select ASYNC_PQ
|
||||
select ASYNC_XOR
|
||||
|
||||
config ASYNC_RAID6_TEST
|
||||
tristate "Self test for hardware accelerated raid6 recovery"
|
||||
depends on ASYNC_RAID6_RECOV
|
||||
select ASYNC_MEMCPY
|
||||
---help---
|
||||
This is a one-shot self test that permutes through the
|
||||
recovery of all the possible two disk failure scenarios for a
|
||||
N-disk array. Recovery is performed with the asynchronous
|
||||
raid6 recovery routines, and will optionally use an offload
|
||||
engine if one is available.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config ASYNC_TX_DISABLE_PQ_VAL_DMA
|
||||
bool
|
||||
|
||||
+1
-17
@@ -121,7 +121,7 @@ config MD_RAID10
|
||||
config MD_RAID456
|
||||
tristate "RAID-4/RAID-5/RAID-6 mode"
|
||||
depends on BLK_DEV_MD
|
||||
select MD_RAID6_PQ
|
||||
select RAID6_PQ
|
||||
select ASYNC_MEMCPY
|
||||
select ASYNC_XOR
|
||||
select ASYNC_PQ
|
||||
@@ -165,22 +165,6 @@ config MULTICORE_RAID456
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MD_RAID6_PQ
|
||||
tristate
|
||||
|
||||
config ASYNC_RAID6_TEST
|
||||
tristate "Self test for hardware accelerated raid6 recovery"
|
||||
depends on MD_RAID6_PQ
|
||||
select ASYNC_RAID6_RECOV
|
||||
---help---
|
||||
This is a one-shot self test that permutes through the
|
||||
recovery of all the possible two disk failure scenarios for a
|
||||
N-disk array. Recovery is performed with the asynchronous
|
||||
raid6 recovery routines, and will optionally use an offload
|
||||
engine if one is available.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MD_MULTIPATH
|
||||
tristate "Multipath I/O support"
|
||||
depends on BLK_DEV_MD
|
||||
|
||||
@@ -12,13 +12,6 @@ dm-log-userspace-y \
|
||||
+= dm-log-userspace-base.o dm-log-userspace-transfer.o
|
||||
md-mod-y += md.o bitmap.o
|
||||
raid456-y += raid5.o
|
||||
raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \
|
||||
raid6int1.o raid6int2.o raid6int4.o \
|
||||
raid6int8.o raid6int16.o raid6int32.o \
|
||||
raid6altivec1.o raid6altivec2.o raid6altivec4.o \
|
||||
raid6altivec8.o \
|
||||
raid6mmx.o raid6sse1.o raid6sse2.o
|
||||
hostprogs-y += mktables
|
||||
|
||||
# Note: link order is important. All raid personalities
|
||||
# and must come before md.o, as they each initialise
|
||||
@@ -29,7 +22,6 @@ obj-$(CONFIG_MD_LINEAR) += linear.o
|
||||
obj-$(CONFIG_MD_RAID0) += raid0.o
|
||||
obj-$(CONFIG_MD_RAID1) += raid1.o
|
||||
obj-$(CONFIG_MD_RAID10) += raid10.o
|
||||
obj-$(CONFIG_MD_RAID6_PQ) += raid6_pq.o
|
||||
obj-$(CONFIG_MD_RAID456) += raid456.o
|
||||
obj-$(CONFIG_MD_MULTIPATH) += multipath.o
|
||||
obj-$(CONFIG_MD_FAULTY) += faulty.o
|
||||
@@ -45,75 +37,6 @@ obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
|
||||
obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
|
||||
obj-$(CONFIG_DM_ZERO) += dm-zero.o
|
||||
|
||||
quiet_cmd_unroll = UNROLL $@
|
||||
cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \
|
||||
< $< > $@ || ( rm -f $@ && exit 1 )
|
||||
|
||||
ifeq ($(CONFIG_ALTIVEC),y)
|
||||
altivec_flags := -maltivec -mabi=altivec
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DM_UEVENT),y)
|
||||
dm-mod-objs += dm-uevent.o
|
||||
endif
|
||||
|
||||
targets += raid6int1.c
|
||||
$(obj)/raid6int1.c: UNROLL := 1
|
||||
$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int2.c
|
||||
$(obj)/raid6int2.c: UNROLL := 2
|
||||
$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int4.c
|
||||
$(obj)/raid6int4.c: UNROLL := 4
|
||||
$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int8.c
|
||||
$(obj)/raid6int8.c: UNROLL := 8
|
||||
$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int16.c
|
||||
$(obj)/raid6int16.c: UNROLL := 16
|
||||
$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int32.c
|
||||
$(obj)/raid6int32.c: UNROLL := 32
|
||||
$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec1.o += $(altivec_flags)
|
||||
targets += raid6altivec1.c
|
||||
$(obj)/raid6altivec1.c: UNROLL := 1
|
||||
$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec2.o += $(altivec_flags)
|
||||
targets += raid6altivec2.c
|
||||
$(obj)/raid6altivec2.c: UNROLL := 2
|
||||
$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec4.o += $(altivec_flags)
|
||||
targets += raid6altivec4.c
|
||||
$(obj)/raid6altivec4.c: UNROLL := 4
|
||||
$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec8.o += $(altivec_flags)
|
||||
targets += raid6altivec8.c
|
||||
$(obj)/raid6altivec8.c: UNROLL := 8
|
||||
$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
quiet_cmd_mktable = TABLE $@
|
||||
cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 )
|
||||
|
||||
targets += raid6tables.c
|
||||
$(obj)/raid6tables.c: $(obj)/mktables FORCE
|
||||
$(call if_changed,mktable)
|
||||
|
||||
+281
-231
File diff suppressed because it is too large
Load Diff
@@ -222,6 +222,10 @@ struct bitmap {
|
||||
unsigned long file_pages; /* number of pages in the file */
|
||||
int last_page_size; /* bytes in the last page */
|
||||
|
||||
unsigned long logattrs; /* used when filemap_attr doesn't exist
|
||||
* because we are working with a dirty_log
|
||||
*/
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
int allclean;
|
||||
@@ -243,12 +247,14 @@ struct bitmap {
|
||||
wait_queue_head_t behind_wait;
|
||||
|
||||
struct sysfs_dirent *sysfs_can_clear;
|
||||
|
||||
};
|
||||
|
||||
/* the bitmap API */
|
||||
|
||||
/* these are used only by md/bitmap */
|
||||
int bitmap_create(mddev_t *mddev);
|
||||
int bitmap_load(mddev_t *mddev);
|
||||
void bitmap_flush(mddev_t *mddev);
|
||||
void bitmap_destroy(mddev_t *mddev);
|
||||
|
||||
|
||||
+176
-110
File diff suppressed because it is too large
Load Diff
+54
-1
@@ -29,6 +29,26 @@
|
||||
typedef struct mddev_s mddev_t;
|
||||
typedef struct mdk_rdev_s mdk_rdev_t;
|
||||
|
||||
/* generic plugging support - like that provided with request_queue,
|
||||
* but does not require a request_queue
|
||||
*/
|
||||
struct plug_handle {
|
||||
void (*unplug_fn)(struct plug_handle *);
|
||||
struct timer_list unplug_timer;
|
||||
struct work_struct unplug_work;
|
||||
unsigned long unplug_flag;
|
||||
};
|
||||
#define PLUGGED_FLAG 1
|
||||
void plugger_init(struct plug_handle *plug,
|
||||
void (*unplug_fn)(struct plug_handle *));
|
||||
void plugger_set_plug(struct plug_handle *plug);
|
||||
int plugger_remove_plug(struct plug_handle *plug);
|
||||
static inline void plugger_flush(struct plug_handle *plug)
|
||||
{
|
||||
del_timer_sync(&plug->unplug_timer);
|
||||
cancel_work_sync(&plug->unplug_work);
|
||||
}
|
||||
|
||||
/*
|
||||
* MD's 'extended' device
|
||||
*/
|
||||
@@ -125,6 +145,10 @@ struct mddev_s
|
||||
int suspended;
|
||||
atomic_t active_io;
|
||||
int ro;
|
||||
int sysfs_active; /* set when sysfs deletes
|
||||
* are happening, so run/
|
||||
* takeover/stop are not safe
|
||||
*/
|
||||
|
||||
struct gendisk *gendisk;
|
||||
|
||||
@@ -297,9 +321,14 @@ struct mddev_s
|
||||
* hot-adding a bitmap. It should
|
||||
* eventually be settable by sysfs.
|
||||
*/
|
||||
/* When md is serving under dm, it might use a
|
||||
* dirty_log to store the bits.
|
||||
*/
|
||||
struct dm_dirty_log *log;
|
||||
|
||||
struct mutex mutex;
|
||||
unsigned long chunksize;
|
||||
unsigned long daemon_sleep; /* how many seconds between updates? */
|
||||
unsigned long daemon_sleep; /* how many jiffies between updates? */
|
||||
unsigned long max_write_behind; /* write-behind mode */
|
||||
int external;
|
||||
} bitmap_info;
|
||||
@@ -308,6 +337,8 @@ struct mddev_s
|
||||
struct list_head all_mddevs;
|
||||
|
||||
struct attribute_group *to_remove;
|
||||
struct plug_handle *plug; /* if used by personality */
|
||||
|
||||
/* Generic barrier handling.
|
||||
* If there is a pending barrier request, all other
|
||||
* writes are blocked while the devices are flushed.
|
||||
@@ -318,6 +349,7 @@ struct mddev_s
|
||||
struct bio *barrier;
|
||||
atomic_t flush_pending;
|
||||
struct work_struct barrier_work;
|
||||
struct work_struct event_work; /* used by dm to report failure event */
|
||||
};
|
||||
|
||||
|
||||
@@ -382,6 +414,18 @@ struct md_sysfs_entry {
|
||||
};
|
||||
extern struct attribute_group md_bitmap_group;
|
||||
|
||||
static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name)
|
||||
{
|
||||
if (sd)
|
||||
return sysfs_get_dirent(sd, NULL, name);
|
||||
return sd;
|
||||
}
|
||||
static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd)
|
||||
{
|
||||
if (sd)
|
||||
sysfs_notify_dirent(sd);
|
||||
}
|
||||
|
||||
static inline char * mdname (mddev_t * mddev)
|
||||
{
|
||||
return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
|
||||
@@ -474,5 +518,14 @@ extern int md_integrity_register(mddev_t *mddev);
|
||||
extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
|
||||
extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
|
||||
extern void restore_bitmap_write_access(struct file *file);
|
||||
extern void md_unplug(mddev_t *mddev);
|
||||
|
||||
extern void mddev_init(mddev_t *mddev);
|
||||
extern int md_run(mddev_t *mddev);
|
||||
extern void md_stop(mddev_t *mddev);
|
||||
extern void md_stop_writes(mddev_t *mddev);
|
||||
extern void md_rdev_init(mdk_rdev_t *rdev);
|
||||
|
||||
extern void mddev_suspend(mddev_t *mddev);
|
||||
extern void mddev_resume(mddev_t *mddev);
|
||||
#endif /* _MD_MD_H */
|
||||
|
||||
@@ -825,11 +825,29 @@ static int make_request(mddev_t *mddev, struct bio * bio)
|
||||
*/
|
||||
bp = bio_split(bio,
|
||||
chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
|
||||
|
||||
/* Each of these 'make_request' calls will call 'wait_barrier'.
|
||||
* If the first succeeds but the second blocks due to the resync
|
||||
* thread raising the barrier, we will deadlock because the
|
||||
* IO to the underlying device will be queued in generic_make_request
|
||||
* and will never complete, so will never reduce nr_pending.
|
||||
* So increment nr_waiting here so no new raise_barriers will
|
||||
* succeed, and so the second wait_barrier cannot block.
|
||||
*/
|
||||
spin_lock_irq(&conf->resync_lock);
|
||||
conf->nr_waiting++;
|
||||
spin_unlock_irq(&conf->resync_lock);
|
||||
|
||||
if (make_request(mddev, &bp->bio1))
|
||||
generic_make_request(&bp->bio1);
|
||||
if (make_request(mddev, &bp->bio2))
|
||||
generic_make_request(&bp->bio2);
|
||||
|
||||
spin_lock_irq(&conf->resync_lock);
|
||||
conf->nr_waiting--;
|
||||
wake_up(&conf->wait_barrier);
|
||||
spin_unlock_irq(&conf->resync_lock);
|
||||
|
||||
bio_pair_release(bp);
|
||||
return 0;
|
||||
bad_map:
|
||||
|
||||
+108
-72
@@ -201,11 +201,11 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
|
||||
if (test_bit(STRIPE_HANDLE, &sh->state)) {
|
||||
if (test_bit(STRIPE_DELAYED, &sh->state)) {
|
||||
list_add_tail(&sh->lru, &conf->delayed_list);
|
||||
blk_plug_device(conf->mddev->queue);
|
||||
plugger_set_plug(&conf->plug);
|
||||
} else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
|
||||
sh->bm_seq - conf->seq_write > 0) {
|
||||
list_add_tail(&sh->lru, &conf->bitmap_list);
|
||||
blk_plug_device(conf->mddev->queue);
|
||||
plugger_set_plug(&conf->plug);
|
||||
} else {
|
||||
clear_bit(STRIPE_BIT_DELAY, &sh->state);
|
||||
list_add_tail(&sh->lru, &conf->handle_list);
|
||||
@@ -434,7 +434,6 @@ static int has_failed(raid5_conf_t *conf)
|
||||
}
|
||||
|
||||
static void unplug_slaves(mddev_t *mddev);
|
||||
static void raid5_unplug_device(struct request_queue *q);
|
||||
|
||||
static struct stripe_head *
|
||||
get_active_stripe(raid5_conf_t *conf, sector_t sector,
|
||||
@@ -464,7 +463,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector,
|
||||
< (conf->max_nr_stripes *3/4)
|
||||
|| !conf->inactive_blocked),
|
||||
conf->device_lock,
|
||||
raid5_unplug_device(conf->mddev->queue)
|
||||
md_raid5_unplug_device(conf)
|
||||
);
|
||||
conf->inactive_blocked = 0;
|
||||
} else
|
||||
@@ -1337,10 +1336,14 @@ static int grow_stripes(raid5_conf_t *conf, int num)
|
||||
struct kmem_cache *sc;
|
||||
int devs = max(conf->raid_disks, conf->previous_raid_disks);
|
||||
|
||||
sprintf(conf->cache_name[0],
|
||||
"raid%d-%s", conf->level, mdname(conf->mddev));
|
||||
sprintf(conf->cache_name[1],
|
||||
"raid%d-%s-alt", conf->level, mdname(conf->mddev));
|
||||
if (conf->mddev->gendisk)
|
||||
sprintf(conf->cache_name[0],
|
||||
"raid%d-%s", conf->level, mdname(conf->mddev));
|
||||
else
|
||||
sprintf(conf->cache_name[0],
|
||||
"raid%d-%p", conf->level, conf->mddev);
|
||||
sprintf(conf->cache_name[1], "%s-alt", conf->cache_name[0]);
|
||||
|
||||
conf->active_name = 0;
|
||||
sc = kmem_cache_create(conf->cache_name[conf->active_name],
|
||||
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
|
||||
@@ -3614,7 +3617,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf)
|
||||
list_add_tail(&sh->lru, &conf->hold_list);
|
||||
}
|
||||
} else
|
||||
blk_plug_device(conf->mddev->queue);
|
||||
plugger_set_plug(&conf->plug);
|
||||
}
|
||||
|
||||
static void activate_bit_delay(raid5_conf_t *conf)
|
||||
@@ -3655,36 +3658,44 @@ static void unplug_slaves(mddev_t *mddev)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void raid5_unplug_device(struct request_queue *q)
|
||||
void md_raid5_unplug_device(raid5_conf_t *conf)
|
||||
{
|
||||
mddev_t *mddev = q->queuedata;
|
||||
raid5_conf_t *conf = mddev->private;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&conf->device_lock, flags);
|
||||
|
||||
if (blk_remove_plug(q)) {
|
||||
if (plugger_remove_plug(&conf->plug)) {
|
||||
conf->seq_flush++;
|
||||
raid5_activate_delayed(conf);
|
||||
}
|
||||
md_wakeup_thread(mddev->thread);
|
||||
md_wakeup_thread(conf->mddev->thread);
|
||||
|
||||
spin_unlock_irqrestore(&conf->device_lock, flags);
|
||||
|
||||
unplug_slaves(mddev);
|
||||
unplug_slaves(conf->mddev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(md_raid5_unplug_device);
|
||||
|
||||
static void raid5_unplug(struct plug_handle *plug)
|
||||
{
|
||||
raid5_conf_t *conf = container_of(plug, raid5_conf_t, plug);
|
||||
md_raid5_unplug_device(conf);
|
||||
}
|
||||
|
||||
static int raid5_congested(void *data, int bits)
|
||||
static void raid5_unplug_queue(struct request_queue *q)
|
||||
{
|
||||
mddev_t *mddev = q->queuedata;
|
||||
md_raid5_unplug_device(mddev->private);
|
||||
}
|
||||
|
||||
int md_raid5_congested(mddev_t *mddev, int bits)
|
||||
{
|
||||
mddev_t *mddev = data;
|
||||
raid5_conf_t *conf = mddev->private;
|
||||
|
||||
/* No difference between reads and writes. Just check
|
||||
* how busy the stripe_cache is
|
||||
*/
|
||||
|
||||
if (mddev_congested(mddev, bits))
|
||||
return 1;
|
||||
if (conf->inactive_blocked)
|
||||
return 1;
|
||||
if (conf->quiesce)
|
||||
@@ -3694,6 +3705,15 @@ static int raid5_congested(void *data, int bits)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(md_raid5_congested);
|
||||
|
||||
static int raid5_congested(void *data, int bits)
|
||||
{
|
||||
mddev_t *mddev = data;
|
||||
|
||||
return mddev_congested(mddev, bits) ||
|
||||
md_raid5_congested(mddev, bits);
|
||||
}
|
||||
|
||||
/* We want read requests to align with chunks where possible,
|
||||
* but write requests don't need to.
|
||||
@@ -4075,7 +4095,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
|
||||
* add failed due to overlap. Flush everything
|
||||
* and wait a while
|
||||
*/
|
||||
raid5_unplug_device(mddev->queue);
|
||||
md_raid5_unplug_device(conf);
|
||||
release_stripe(sh);
|
||||
schedule();
|
||||
goto retry;
|
||||
@@ -4566,6 +4586,32 @@ raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
raid5_set_cache_size(mddev_t *mddev, int size)
|
||||
{
|
||||
raid5_conf_t *conf = mddev->private;
|
||||
int err;
|
||||
|
||||
if (size <= 16 || size > 32768)
|
||||
return -EINVAL;
|
||||
while (size < conf->max_nr_stripes) {
|
||||
if (drop_one_stripe(conf))
|
||||
conf->max_nr_stripes--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
err = md_allow_write(mddev);
|
||||
if (err)
|
||||
return err;
|
||||
while (size > conf->max_nr_stripes) {
|
||||
if (grow_one_stripe(conf))
|
||||
conf->max_nr_stripes++;
|
||||
else break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(raid5_set_cache_size);
|
||||
|
||||
static ssize_t
|
||||
raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
|
||||
{
|
||||
@@ -4580,22 +4626,9 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
|
||||
|
||||
if (strict_strtoul(page, 10, &new))
|
||||
return -EINVAL;
|
||||
if (new <= 16 || new > 32768)
|
||||
return -EINVAL;
|
||||
while (new < conf->max_nr_stripes) {
|
||||
if (drop_one_stripe(conf))
|
||||
conf->max_nr_stripes--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
err = md_allow_write(mddev);
|
||||
err = raid5_set_cache_size(mddev, new);
|
||||
if (err)
|
||||
return err;
|
||||
while (new > conf->max_nr_stripes) {
|
||||
if (grow_one_stripe(conf))
|
||||
conf->max_nr_stripes++;
|
||||
else break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -4958,7 +4991,7 @@ static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded
|
||||
static int run(mddev_t *mddev)
|
||||
{
|
||||
raid5_conf_t *conf;
|
||||
int working_disks = 0, chunk_size;
|
||||
int working_disks = 0;
|
||||
int dirty_parity_disks = 0;
|
||||
mdk_rdev_t *rdev;
|
||||
sector_t reshape_offset = 0;
|
||||
@@ -5144,43 +5177,48 @@ static int run(mddev_t *mddev)
|
||||
"reshape");
|
||||
}
|
||||
|
||||
/* read-ahead size must cover two whole stripes, which is
|
||||
* 2 * (datadisks) * chunksize where 'n' is the number of raid devices
|
||||
*/
|
||||
{
|
||||
|
||||
/* Ok, everything is just fine now */
|
||||
if (mddev->to_remove == &raid5_attrs_group)
|
||||
mddev->to_remove = NULL;
|
||||
else if (mddev->kobj.sd &&
|
||||
sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
|
||||
printk(KERN_WARNING
|
||||
"raid5: failed to create sysfs attributes for %s\n",
|
||||
mdname(mddev));
|
||||
md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
|
||||
|
||||
plugger_init(&conf->plug, raid5_unplug);
|
||||
mddev->plug = &conf->plug;
|
||||
if (mddev->queue) {
|
||||
int chunk_size;
|
||||
/* read-ahead size must cover two whole stripes, which
|
||||
* is 2 * (datadisks) * chunksize where 'n' is the
|
||||
* number of raid devices
|
||||
*/
|
||||
int data_disks = conf->previous_raid_disks - conf->max_degraded;
|
||||
int stripe = data_disks *
|
||||
((mddev->chunk_sectors << 9) / PAGE_SIZE);
|
||||
if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
|
||||
mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
|
||||
|
||||
blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
|
||||
|
||||
mddev->queue->backing_dev_info.congested_data = mddev;
|
||||
mddev->queue->backing_dev_info.congested_fn = raid5_congested;
|
||||
mddev->queue->queue_lock = &conf->device_lock;
|
||||
mddev->queue->unplug_fn = raid5_unplug_queue;
|
||||
|
||||
chunk_size = mddev->chunk_sectors << 9;
|
||||
blk_queue_io_min(mddev->queue, chunk_size);
|
||||
blk_queue_io_opt(mddev->queue, chunk_size *
|
||||
(conf->raid_disks - conf->max_degraded));
|
||||
|
||||
list_for_each_entry(rdev, &mddev->disks, same_set)
|
||||
disk_stack_limits(mddev->gendisk, rdev->bdev,
|
||||
rdev->data_offset << 9);
|
||||
}
|
||||
|
||||
/* Ok, everything is just fine now */
|
||||
if (mddev->to_remove == &raid5_attrs_group)
|
||||
mddev->to_remove = NULL;
|
||||
else if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
|
||||
printk(KERN_WARNING
|
||||
"md/raid:%s: failed to create sysfs attributes.\n",
|
||||
mdname(mddev));
|
||||
|
||||
mddev->queue->queue_lock = &conf->device_lock;
|
||||
|
||||
mddev->queue->unplug_fn = raid5_unplug_device;
|
||||
mddev->queue->backing_dev_info.congested_data = mddev;
|
||||
mddev->queue->backing_dev_info.congested_fn = raid5_congested;
|
||||
|
||||
md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
|
||||
|
||||
blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
|
||||
chunk_size = mddev->chunk_sectors << 9;
|
||||
blk_queue_io_min(mddev->queue, chunk_size);
|
||||
blk_queue_io_opt(mddev->queue, chunk_size *
|
||||
(conf->raid_disks - conf->max_degraded));
|
||||
|
||||
list_for_each_entry(rdev, &mddev->disks, same_set)
|
||||
disk_stack_limits(mddev->gendisk, rdev->bdev,
|
||||
rdev->data_offset << 9);
|
||||
|
||||
return 0;
|
||||
abort:
|
||||
md_unregister_thread(mddev->thread);
|
||||
@@ -5200,8 +5238,9 @@ static int stop(mddev_t *mddev)
|
||||
|
||||
md_unregister_thread(mddev->thread);
|
||||
mddev->thread = NULL;
|
||||
mddev->queue->backing_dev_info.congested_fn = NULL;
|
||||
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
|
||||
if (mddev->queue)
|
||||
mddev->queue->backing_dev_info.congested_fn = NULL;
|
||||
plugger_flush(&conf->plug); /* the unplug fn references 'conf'*/
|
||||
free_conf(conf);
|
||||
mddev->private = NULL;
|
||||
mddev->to_remove = &raid5_attrs_group;
|
||||
@@ -5545,10 +5584,7 @@ static int raid5_start_reshape(mddev_t *mddev)
|
||||
sprintf(nm, "rd%d", rdev->raid_disk);
|
||||
if (sysfs_create_link(&mddev->kobj,
|
||||
&rdev->kobj, nm))
|
||||
printk(KERN_WARNING
|
||||
"md/raid:%s: failed to create "
|
||||
" link %s\n",
|
||||
mdname(mddev), nm);
|
||||
/* Failure here is OK */;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@@ -5603,7 +5639,7 @@ static void end_reshape(raid5_conf_t *conf)
|
||||
/* read-ahead size must cover two whole stripes, which is
|
||||
* 2 * (datadisks) * chunksize where 'n' is the number of raid devices
|
||||
*/
|
||||
{
|
||||
if (conf->mddev->queue) {
|
||||
int data_disks = conf->raid_disks - conf->max_degraded;
|
||||
int stripe = data_disks * ((conf->chunk_sectors << 9)
|
||||
/ PAGE_SIZE);
|
||||
|
||||
+8
-1
@@ -388,7 +388,7 @@ struct raid5_private_data {
|
||||
* two caches.
|
||||
*/
|
||||
int active_name;
|
||||
char cache_name[2][20];
|
||||
char cache_name[2][32];
|
||||
struct kmem_cache *slab_cache; /* for allocating stripes */
|
||||
|
||||
int seq_flush, seq_write;
|
||||
@@ -398,6 +398,9 @@ struct raid5_private_data {
|
||||
* (fresh device added).
|
||||
* Cleared when a sync completes.
|
||||
*/
|
||||
|
||||
struct plug_handle plug;
|
||||
|
||||
/* per cpu variables */
|
||||
struct raid5_percpu {
|
||||
struct page *spare_page; /* Used when checking P/Q in raid6 */
|
||||
@@ -497,4 +500,8 @@ static inline int algorithm_is_DDF(int layout)
|
||||
{
|
||||
return layout >= 8 && layout <= 10;
|
||||
}
|
||||
|
||||
extern int md_raid5_congested(mddev_t *mddev, int bits);
|
||||
extern void md_raid5_unplug_device(raid5_conf_t *conf);
|
||||
extern int raid5_set_cache_size(mddev_t *mddev, int size);
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,9 @@ config BINARY_PRINTF
|
||||
|
||||
menu "Library routines"
|
||||
|
||||
config RAID6_PQ
|
||||
tristate
|
||||
|
||||
config BITREVERSE
|
||||
tristate
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
|
||||
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
|
||||
obj-$(CONFIG_LZO_COMPRESS) += lzo/
|
||||
obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
|
||||
obj-$(CONFIG_RAID6_PQ) += raid6/
|
||||
|
||||
lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
|
||||
lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
obj-$(CONFIG_RAID6_PQ) += raid6_pq.o
|
||||
|
||||
raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \
|
||||
raid6int1.o raid6int2.o raid6int4.o \
|
||||
raid6int8.o raid6int16.o raid6int32.o \
|
||||
raid6altivec1.o raid6altivec2.o raid6altivec4.o \
|
||||
raid6altivec8.o \
|
||||
raid6mmx.o raid6sse1.o raid6sse2.o
|
||||
hostprogs-y += mktables
|
||||
|
||||
quiet_cmd_unroll = UNROLL $@
|
||||
cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \
|
||||
< $< > $@ || ( rm -f $@ && exit 1 )
|
||||
|
||||
ifeq ($(CONFIG_ALTIVEC),y)
|
||||
altivec_flags := -maltivec -mabi=altivec
|
||||
endif
|
||||
|
||||
targets += raid6int1.c
|
||||
$(obj)/raid6int1.c: UNROLL := 1
|
||||
$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int2.c
|
||||
$(obj)/raid6int2.c: UNROLL := 2
|
||||
$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int4.c
|
||||
$(obj)/raid6int4.c: UNROLL := 4
|
||||
$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int8.c
|
||||
$(obj)/raid6int8.c: UNROLL := 8
|
||||
$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int16.c
|
||||
$(obj)/raid6int16.c: UNROLL := 16
|
||||
$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += raid6int32.c
|
||||
$(obj)/raid6int32.c: UNROLL := 32
|
||||
$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec1.o += $(altivec_flags)
|
||||
targets += raid6altivec1.c
|
||||
$(obj)/raid6altivec1.c: UNROLL := 1
|
||||
$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec2.o += $(altivec_flags)
|
||||
targets += raid6altivec2.c
|
||||
$(obj)/raid6altivec2.c: UNROLL := 2
|
||||
$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec4.o += $(altivec_flags)
|
||||
targets += raid6altivec4.c
|
||||
$(obj)/raid6altivec4.c: UNROLL := 4
|
||||
$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
CFLAGS_raid6altivec8.o += $(altivec_flags)
|
||||
targets += raid6altivec8.c
|
||||
$(obj)/raid6altivec8.c: UNROLL := 8
|
||||
$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
quiet_cmd_mktable = TABLE $@
|
||||
cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 )
|
||||
|
||||
targets += raid6tables.c
|
||||
$(obj)/raid6tables.c: $(obj)/mktables FORCE
|
||||
$(call if_changed,mktable)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user