Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea88eeac authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'md-3.8' of git://neil.brown.name/md

Pull md update from Neil Brown:
 "Mostly just little fixes.  Probably biggest part is AVX accelerated
  RAID6 calculations."

* tag 'md-3.8' of git://neil.brown.name/md:
  md/raid5: add blktrace calls
  md/raid5: use async_tx_quiesce() instead of open-coding it.
  md: Use ->curr_resync as last completed request when cleanly aborting resync.
  lib/raid6: build proper files on corresponding arch
  lib/raid6: Add AVX2 optimized gen_syndrome functions
  lib/raid6: Add AVX2 optimized recovery functions
  md: Update checkpoint of resync/recovery based on time.
  md:Add place to update ->recovery_cp.
  md.c: re-indent various 'switch' statements.
  md: close race between removing and adding a device.
  md: removed unused variable in calc_sb_1_csm.
parents 848b8141 a9add5d9
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -123,9 +123,10 @@ cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTI
# does binutils support specific instructions?
asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)

KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)

LDFLAGS := -m elf_$(UTS_MACHINE)

+133 −123
Original line number Diff line number Diff line
@@ -1414,12 +1414,11 @@ static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb)
	unsigned long long newcsum;
	int size = 256 + le32_to_cpu(sb->max_dev)*2;
	__le32 *isuper = (__le32*)sb;
	int i;

	disk_csum = sb->sb_csum;
	sb->sb_csum = 0;
	newcsum = 0;
	for (i=0; size>=4; size -= 4 )
	for (; size >= 4; size -= 4)
		newcsum += le32_to_cpu(*isuper++);

	if (size == 2)
@@ -4753,6 +4752,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
	}
	mddev_get(mddev);
	spin_unlock(&all_mddevs_lock);
	if (entry->store == new_dev_store)
		flush_workqueue(md_misc_wq);
	rv = mddev_lock(mddev);
	if (!rv) {
		rv = entry->store(mddev, page, length);
@@ -6346,8 +6347,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
	 * Commands dealing with the RAID driver but not any
	 * particular array:
	 */
	switch (cmd)
	{
	switch (cmd) {
	case RAID_VERSION:
		err = get_version(argp);
		goto done;
@@ -6398,6 +6398,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
		goto abort;
	}

	if (cmd == ADD_NEW_DISK)
		/* need to ensure md_delayed_delete() has completed */
		flush_workqueue(md_misc_wq);

	err = mddev_lock(mddev);
	if (err) {
		printk(KERN_INFO 
@@ -6406,10 +6410,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
		goto abort;
	}

	switch (cmd)
	{
		case SET_ARRAY_INFO:
			{
	if (cmd == SET_ARRAY_INFO) {
		mdu_array_info_t info;
		if (!arg)
			memset(&info, 0, sizeof(info));
@@ -6446,10 +6447,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
			       " array info. %d\n", err);
			goto abort_unlock;
		}
			}
		goto done_unlock;

		default:;
	}

	/*
@@ -6468,8 +6466,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
	/*
	 * Commands even a read-only array can execute:
	 */
	switch (cmd)
	{
	switch (cmd) {
	case GET_BITMAP_FILE:
		err = get_bitmap_file(mddev, argp);
		goto done_unlock;
@@ -6535,8 +6532,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
		}
	}

	switch (cmd)
	{
	switch (cmd) {
	case ADD_NEW_DISK:
	{
		mdu_disk_info_t info;
@@ -7184,6 +7180,7 @@ void md_done_sync(struct mddev *mddev, int blocks, int ok)
	wake_up(&mddev->recovery_wait);
	if (!ok) {
		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
		set_bit(MD_RECOVERY_ERROR, &mddev->recovery);
		md_wakeup_thread(mddev->thread);
		// stop recovery, signal do_sync ....
	}
@@ -7281,6 +7278,7 @@ EXPORT_SYMBOL_GPL(md_allow_write);

#define SYNC_MARKS	10
#define	SYNC_MARK_STEP	(3*HZ)
#define UPDATE_FREQUENCY (5*60*HZ)
void md_do_sync(struct md_thread *thread)
{
	struct mddev *mddev = thread->mddev;
@@ -7289,6 +7287,7 @@ void md_do_sync(struct md_thread *thread)
		 window;
	sector_t max_sectors,j, io_sectors;
	unsigned long mark[SYNC_MARKS];
	unsigned long update_time;
	sector_t mark_cnt[SYNC_MARKS];
	int last_mark,m;
	struct list_head *tmp;
@@ -7448,6 +7447,7 @@ void md_do_sync(struct md_thread *thread)
	mddev->curr_resync_completed = j;
	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
	md_new_event(mddev);
	update_time = jiffies;

	blk_start_plug(&plug);
	while (j < max_sectors) {
@@ -7459,6 +7459,7 @@ void md_do_sync(struct md_thread *thread)
		    ((mddev->curr_resync > mddev->curr_resync_completed &&
		      (mddev->curr_resync - mddev->curr_resync_completed)
		      > (max_sectors >> 4)) ||
		     time_after_eq(jiffies, update_time + UPDATE_FREQUENCY) ||
		     (j - mddev->curr_resync_completed)*2
		     >= mddev->resync_max - mddev->curr_resync_completed
			    )) {
@@ -7466,6 +7467,10 @@ void md_do_sync(struct md_thread *thread)
			wait_event(mddev->recovery_wait,
				   atomic_read(&mddev->recovery_active) == 0);
			mddev->curr_resync_completed = j;
			if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
			    j > mddev->recovery_cp)
				mddev->recovery_cp = j;
			update_time = jiffies;
			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
		}
@@ -7570,8 +7575,13 @@ void md_do_sync(struct md_thread *thread)
					printk(KERN_INFO
					       "md: checkpointing %s of %s.\n",
					       desc, mdname(mddev));
					if (test_bit(MD_RECOVERY_ERROR,
						&mddev->recovery))
						mddev->recovery_cp =
							mddev->curr_resync_completed;
					else
						mddev->recovery_cp =
							mddev->curr_resync;
				}
			} else
				mddev->recovery_cp = MaxSector;
+2 −0
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ struct mddev {
	 * REQUEST:  user-space has requested a sync (used with SYNC)
	 * CHECK:    user-space request for check-only, no repair
	 * RESHAPE:  A reshape is happening
	 * ERROR:    sync-action interrupted because io-error
	 *
	 * If neither SYNC or RESHAPE are set, then it is a recovery.
	 */
@@ -320,6 +321,7 @@ struct mddev {
#define	MD_RECOVERY_CHECK	7
#define MD_RECOVERY_RESHAPE	8
#define	MD_RECOVERY_FROZEN	9
#define	MD_RECOVERY_ERROR	10

	unsigned long			recovery;
	/* If a RAID personality determines that recovery (of a particular
+36 −7
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@
#include <linux/cpu.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <trace/events/block.h>

#include "md.h"
#include "raid5.h"
#include "raid0.h"
@@ -182,6 +184,8 @@ static void return_io(struct bio *return_bi)
		return_bi = bi->bi_next;
		bi->bi_next = NULL;
		bi->bi_size = 0;
		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
					 bi, 0);
		bio_endio(bi, 0);
		bi = return_bi;
	}
@@ -670,6 +674,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
			bi->bi_next = NULL;
			if (rrdev)
				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
			trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
					      bi, disk_devt(conf->mddev->gendisk),
					      sh->dev[i].sector);
			generic_make_request(bi);
		}
		if (rrdev) {
@@ -697,6 +704,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
			rbi->bi_io_vec[0].bv_offset = 0;
			rbi->bi_size = STRIPE_SIZE;
			rbi->bi_next = NULL;
			trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
					      rbi, disk_devt(conf->mddev->gendisk),
					      sh->dev[i].sector);
			generic_make_request(rbi);
		}
		if (!rdev && !rrdev) {
@@ -2853,8 +2863,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
	pr_debug("for sector %llu, rmw=%d rcw=%d\n",
		(unsigned long long)sh->sector, rmw, rcw);
	set_bit(STRIPE_HANDLE, &sh->state);
	if (rmw < rcw && rmw > 0)
	if (rmw < rcw && rmw > 0) {
		/* prefer read-modify-write, but need to get some data */
		blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
				  (unsigned long long)sh->sector, rmw);
		for (i = disks; i--; ) {
			struct r5dev *dev = &sh->dev[i];
			if ((dev->towrite || i == sh->pd_idx) &&
@@ -2875,8 +2887,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
				}
			}
		}
	}
	if (rcw <= rmw && rcw > 0) {
		/* want reconstruct write, but need to get some data */
		int qread =0;
		rcw = 0;
		for (i = disks; i--; ) {
			struct r5dev *dev = &sh->dev[i];
@@ -2895,12 +2909,17 @@ static void handle_stripe_dirtying(struct r5conf *conf,
					set_bit(R5_LOCKED, &dev->flags);
					set_bit(R5_Wantread, &dev->flags);
					s->locked++;
					qread++;
				} else {
					set_bit(STRIPE_DELAYED, &sh->state);
					set_bit(STRIPE_HANDLE, &sh->state);
				}
			}
		}
		if (rcw)
			blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
					  (unsigned long long)sh->sector,
					  rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
	}
	/* now if nothing is locked, and if we have enough data,
	 * we can start a write request
@@ -3222,10 +3241,7 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)

		}
	/* done submitting copies, wait for them to complete */
	if (tx) {
		async_tx_ack(tx);
		dma_wait_for_async_tx(tx);
	}
	async_tx_quiesce(&tx);
}

/*
@@ -3901,6 +3917,8 @@ static void raid5_align_endio(struct bio *bi, int error)
	rdev_dec_pending(rdev, conf->mddev);

	if (!error && uptodate) {
		trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
					 raid_bi, 0);
		bio_endio(raid_bi, 0);
		if (atomic_dec_and_test(&conf->active_aligned_reads))
			wake_up(&conf->wait_for_stripe);
@@ -4005,6 +4023,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
		atomic_inc(&conf->active_aligned_reads);
		spin_unlock_irq(&conf->device_lock);

		trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
				      align_bi, disk_devt(mddev->gendisk),
				      raid_bio->bi_sector);
		generic_make_request(align_bi);
		return 1;
	} else {
@@ -4079,6 +4100,7 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
	struct stripe_head *sh;
	struct mddev *mddev = cb->cb.data;
	struct r5conf *conf = mddev->private;
	int cnt = 0;

	if (cb->list.next && !list_empty(&cb->list)) {
		spin_lock_irq(&conf->device_lock);
@@ -4093,9 +4115,11 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
			smp_mb__before_clear_bit();
			clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
			__release_stripe(conf, sh);
			cnt++;
		}
		spin_unlock_irq(&conf->device_lock);
	}
	trace_block_unplug(mddev->queue, cnt, !from_schedule);
	kfree(cb);
}

@@ -4353,6 +4377,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
		if ( rw == WRITE )
			md_write_end(mddev);

		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
					 bi, 0);
		bio_endio(bi, 0);
	}
}
@@ -4729,8 +4755,11 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
		handled++;
	}
	remaining = raid5_dec_bi_active_stripes(raid_bio);
	if (remaining == 0)
	if (remaining == 0) {
		trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
					 raid_bio, 0);
		bio_endio(raid_bio, 0);
	}
	if (atomic_dec_and_test(&conf->active_aligned_reads))
		wake_up(&conf->wait_for_stripe);
	return handled;
+4 −0
Original line number Diff line number Diff line
@@ -98,6 +98,9 @@ extern const struct raid6_calls raid6_altivec1;
extern const struct raid6_calls raid6_altivec2;
extern const struct raid6_calls raid6_altivec4;
extern const struct raid6_calls raid6_altivec8;
extern const struct raid6_calls raid6_avx2x1;
extern const struct raid6_calls raid6_avx2x2;
extern const struct raid6_calls raid6_avx2x4;

struct raid6_recov_calls {
	void (*data2)(int, size_t, int, int, void **);
@@ -109,6 +112,7 @@ struct raid6_recov_calls {

extern const struct raid6_recov_calls raid6_recov_intx1;
extern const struct raid6_recov_calls raid6_recov_ssse3;
extern const struct raid6_recov_calls raid6_recov_avx2;

/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
Loading