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

Commit 9729a6eb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://neil.brown.name/md

* 'for-linus' of git://neil.brown.name/md: (39 commits)
  md/raid5: correctly update sync_completed when we reach max_resync
  md/raid5: add missing call to schedule() after prepare_to_wait()
  md/linear: use call_rcu to free obsolete 'conf' structures.
  md linear: Protecting mddev with rcu locks to avoid races
  md: Move check for bitmap presence to personality code.
  md: remove chunksize rounding from common code.
  md: raid0/linear: ensure device sizes are rounded to chunk size.
  md: move assignment of ->utime so that it never gets skipped.
  md: Push down reconstruction log message to personality code.
  md: merge reconfig and check_reshape methods.
  md: remove unnecessary arguments from ->reconfig method.
  md: raid5: check stripe cache is large enough in start_reshape
  md: raid0: chunk_sectors cleanups.
  md: fix some comments.
  md/raid5: Use is_power_of_2() in raid5_reconfig()/raid6_reconfig().
  md: convert conf->chunk_size and conf->prev_chunk to sectors.
  md: Convert mddev->new_chunk to sectors.
  md: Make mddev->chunk_size sector-based.
  md: raid0 :Enables chunk size other than powers of 2.
  md: prepare for non-power-of-two chunk sizes
  ...
parents 5ae8606d 48606a9f
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -255,14 +255,14 @@ static void status(struct seq_file *seq, mddev_t *mddev)
}


static int reconfig(mddev_t *mddev, int layout, int chunk_size)
static int reshape(mddev_t *mddev)
{
	int mode = layout & ModeMask;
	int count = layout >> ModeShift;
	int mode = mddev->new_layout & ModeMask;
	int count = mddev->new_layout >> ModeShift;
	conf_t *conf = mddev->private;

	if (chunk_size != -1)
		return -EINVAL;
	if (mddev->new_layout < 0)
		return 0;

	/* new layout */
	if (mode == ClearFaults)
@@ -279,6 +279,7 @@ static int reconfig(mddev_t *mddev, int layout, int chunk_size)
		atomic_set(&conf->counters[mode], count);
	} else
		return -EINVAL;
	mddev->new_layout = -1;
	mddev->layout = -1; /* makes sure further changes come through */
	return 0;
}
@@ -298,8 +299,12 @@ static int run(mddev_t *mddev)
{
	mdk_rdev_t *rdev;
	int i;
	conf_t *conf;

	if (md_check_no_bitmap(mddev))
		return -EINVAL;

	conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
	conf = kmalloc(sizeof(*conf), GFP_KERNEL);
	if (!conf)
		return -ENOMEM;

@@ -315,7 +320,7 @@ static int run(mddev_t *mddev)
	md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
	mddev->private = conf;

	reconfig(mddev, mddev->layout, -1);
	reshape(mddev);

	return 0;
}
@@ -338,7 +343,7 @@ static struct mdk_personality faulty_personality =
	.run		= run,
	.stop		= stop,
	.status		= status,
	.reconfig	= reconfig,
	.check_reshape	= reshape,
	.size		= faulty_size,
};

+92 −126
Original line number Diff line number Diff line
@@ -27,19 +27,27 @@
 */
static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
{
	dev_info_t *hash;
	linear_conf_t *conf = mddev_to_conf(mddev);
	sector_t idx = sector >> conf->sector_shift;
	int lo, mid, hi;
	linear_conf_t *conf;

	lo = 0;
	hi = mddev->raid_disks - 1;
	conf = rcu_dereference(mddev->private);

	/*
	 * sector_div(a,b) returns the remainer and sets a to a/b
	 * Binary Search
	 */
	(void)sector_div(idx, conf->spacing);
	hash = conf->hash_table[idx];

	while (sector >= hash->num_sectors + hash->start_sector)
		hash++;
	return hash;
	while (hi > lo) {

		mid = (hi + lo) / 2;
		if (sector < conf->disks[mid].end_sector)
			hi = mid;
		else
			lo = mid + 1;
	}

	return conf->disks + lo;
}

/**
@@ -59,8 +67,10 @@ static int linear_mergeable_bvec(struct request_queue *q,
	unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);

	rcu_read_lock();
	dev0 = which_dev(mddev, sector);
	maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
	maxsectors = dev0->end_sector - sector;
	rcu_read_unlock();

	if (maxsectors < bio_sectors)
		maxsectors = 0;
@@ -79,46 +89,57 @@ static int linear_mergeable_bvec(struct request_queue *q,
static void linear_unplug(struct request_queue *q)
{
	mddev_t *mddev = q->queuedata;
	linear_conf_t *conf = mddev_to_conf(mddev);
	linear_conf_t *conf;
	int i;

	rcu_read_lock();
	conf = rcu_dereference(mddev->private);

	for (i=0; i < mddev->raid_disks; i++) {
		struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
		blk_unplug(r_queue);
	}
	rcu_read_unlock();
}

static int linear_congested(void *data, int bits)
{
	mddev_t *mddev = data;
	linear_conf_t *conf = mddev_to_conf(mddev);
	linear_conf_t *conf;
	int i, ret = 0;

	rcu_read_lock();
	conf = rcu_dereference(mddev->private);

	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
		ret |= bdi_congested(&q->backing_dev_info, bits);
	}

	rcu_read_unlock();
	return ret;
}

static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
{
	linear_conf_t *conf = mddev_to_conf(mddev);
	linear_conf_t *conf;
	sector_t array_sectors;

	rcu_read_lock();
	conf = rcu_dereference(mddev->private);
	WARN_ONCE(sectors || raid_disks,
		  "%s does not support generic reshape\n", __func__);
	array_sectors = conf->array_sectors;
	rcu_read_unlock();

	return conf->array_sectors;
	return array_sectors;
}

static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
{
	linear_conf_t *conf;
	dev_info_t **table;
	mdk_rdev_t *rdev;
	int i, nb_zone, cnt;
	sector_t min_sectors;
	sector_t curr_sector;
	int i, cnt;

	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
			GFP_KERNEL);
@@ -131,6 +152,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
	list_for_each_entry(rdev, &mddev->disks, same_set) {
		int j = rdev->raid_disk;
		dev_info_t *disk = conf->disks + j;
		sector_t sectors;

		if (j < 0 || j >= raid_disks || disk->rdev) {
			printk("linear: disk numbering problem. Aborting!\n");
@@ -138,6 +160,11 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
		}

		disk->rdev = rdev;
		if (mddev->chunk_sectors) {
			sectors = rdev->sectors;
			sector_div(sectors, mddev->chunk_sectors);
			rdev->sectors = sectors * mddev->chunk_sectors;
		}

		blk_queue_stack_limits(mddev->queue,
				       rdev->bdev->bd_disk->queue);
@@ -149,102 +176,24 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);

		disk->num_sectors = rdev->sectors;
		conf->array_sectors += rdev->sectors;

		cnt++;

	}
	if (cnt != raid_disks) {
		printk("linear: not enough drives present. Aborting!\n");
		goto out;
	}

	min_sectors = conf->array_sectors;
	sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
	if (min_sectors == 0)
		min_sectors = 1;

	/* min_sectors is the minimum spacing that will fit the hash
	 * table in one PAGE.  This may be much smaller than needed.
	 * We find the smallest non-terminal set of consecutive devices
	 * that is larger than min_sectors and use the size of that as
	 * the actual spacing
	 */
	conf->spacing = conf->array_sectors;
	for (i=0; i < cnt-1 ; i++) {
		sector_t tmp = 0;
		int j;
		for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
			tmp += conf->disks[j].num_sectors;
		if (tmp >= min_sectors && tmp < conf->spacing)
			conf->spacing = tmp;
	}

	/* spacing may be too large for sector_div to work with,
	 * so we might need to pre-shift
	 */
	conf->sector_shift = 0;
	if (sizeof(sector_t) > sizeof(u32)) {
		sector_t space = conf->spacing;
		while (space > (sector_t)(~(u32)0)) {
			space >>= 1;
			conf->sector_shift++;
		}
	}
	/*
	 * This code was restructured to work around a gcc-2.95.3 internal
	 * compiler error.  Alter it with care.
	 * Here we calculate the device offsets.
	 */
	{
		sector_t sz;
		unsigned round;
		unsigned long base;

		sz = conf->array_sectors >> conf->sector_shift;
		sz += 1; /* force round-up */
		base = conf->spacing >> conf->sector_shift;
		round = sector_div(sz, base);
		nb_zone = sz + (round ? 1 : 0);
	}
	BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));

	conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
					GFP_KERNEL);
	if (!conf->hash_table)
		goto out;
	conf->disks[0].end_sector = conf->disks[0].rdev->sectors;

	/*
	 * Here we generate the linear hash table
	 * First calculate the device offsets.
	 */
	conf->disks[0].start_sector = 0;
	for (i = 1; i < raid_disks; i++)
		conf->disks[i].start_sector =
			conf->disks[i-1].start_sector +
			conf->disks[i-1].num_sectors;

	table = conf->hash_table;
	i = 0;
	for (curr_sector = 0;
	     curr_sector < conf->array_sectors;
	     curr_sector += conf->spacing) {

		while (i < raid_disks-1 &&
		       curr_sector >= conf->disks[i+1].start_sector)
			i++;

		*table ++ = conf->disks + i;
	}

	if (conf->sector_shift) {
		conf->spacing >>= conf->sector_shift;
		/* round spacing up so that when we divide by it,
		 * we err on the side of "too-low", which is safest.
		 */
		conf->spacing++;
	}

	BUG_ON(table - conf->hash_table > nb_zone);
		conf->disks[i].end_sector =
			conf->disks[i-1].end_sector +
			conf->disks[i].rdev->sectors;

	return conf;

@@ -257,6 +206,8 @@ static int linear_run (mddev_t *mddev)
{
	linear_conf_t *conf;

	if (md_check_no_bitmap(mddev))
		return -EINVAL;
	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
	conf = linear_conf(mddev, mddev->raid_disks);

@@ -272,6 +223,12 @@ static int linear_run (mddev_t *mddev)
	return 0;
}

static void free_conf(struct rcu_head *head)
{
	linear_conf_t *conf = container_of(head, linear_conf_t, rcu);
	kfree(conf);
}

static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
{
	/* Adding a drive to a linear array allows the array to grow.
@@ -282,7 +239,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
	 * The current one is never freed until the array is stopped.
	 * This avoids races.
	 */
	linear_conf_t *newconf;
	linear_conf_t *newconf, *oldconf;

	if (rdev->saved_raid_disk != mddev->raid_disks)
		return -EINVAL;
@@ -294,25 +251,29 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
	if (!newconf)
		return -ENOMEM;

	newconf->prev = mddev_to_conf(mddev);
	mddev->private = newconf;
	oldconf = rcu_dereference(mddev->private);
	mddev->raid_disks++;
	rcu_assign_pointer(mddev->private, newconf);
	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
	set_capacity(mddev->gendisk, mddev->array_sectors);
	call_rcu(&oldconf->rcu, free_conf);
	return 0;
}

static int linear_stop (mddev_t *mddev)
{
	linear_conf_t *conf = mddev_to_conf(mddev);
	linear_conf_t *conf = mddev->private;

	/*
	 * We do not require rcu protection here since
	 * we hold reconfig_mutex for both linear_add and
	 * linear_stop, so they cannot race.
	 * We should make sure any old 'conf's are properly
	 * freed though.
	 */
	rcu_barrier();
	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
	do {
		linear_conf_t *t = conf->prev;
		kfree(conf->hash_table);
	kfree(conf);
		conf = t;
	} while (conf);

	return 0;
}
@@ -322,6 +283,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
	const int rw = bio_data_dir(bio);
	mddev_t *mddev = q->queuedata;
	dev_info_t *tmp_dev;
	sector_t start_sector;
	int cpu;

	if (unlikely(bio_barrier(bio))) {
@@ -335,33 +297,36 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
		      bio_sectors(bio));
	part_stat_unlock();

	rcu_read_lock();
	tmp_dev = which_dev(mddev, bio->bi_sector);
	start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;

	if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
					tmp_dev->start_sector)
		     || (bio->bi_sector <
			 tmp_dev->start_sector))) {

	if (unlikely(bio->bi_sector >= (tmp_dev->end_sector)
		     || (bio->bi_sector < start_sector))) {
		char b[BDEVNAME_SIZE];

		printk("linear_make_request: Sector %llu out of bounds on "
			"dev %s: %llu sectors, offset %llu\n",
			(unsigned long long)bio->bi_sector,
			bdevname(tmp_dev->rdev->bdev, b),
			(unsigned long long)tmp_dev->num_sectors,
			(unsigned long long)tmp_dev->start_sector);
			(unsigned long long)tmp_dev->rdev->sectors,
			(unsigned long long)start_sector);
		rcu_read_unlock();
		bio_io_error(bio);
		return 0;
	}
	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
		     tmp_dev->start_sector + tmp_dev->num_sectors)) {
		     tmp_dev->end_sector)) {
		/* This bio crosses a device boundary, so we have to
		 * split it.
		 */
		struct bio_pair *bp;
		sector_t end_sector = tmp_dev->end_sector;

		rcu_read_unlock();

		bp = bio_split(bio,
			       tmp_dev->start_sector + tmp_dev->num_sectors
			       - bio->bi_sector);
		bp = bio_split(bio, end_sector - bio->bi_sector);

		if (linear_make_request(q, &bp->bio1))
			generic_make_request(&bp->bio1);
@@ -372,8 +337,9 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
	}
		    
	bio->bi_bdev = tmp_dev->rdev->bdev;
	bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
	bio->bi_sector = bio->bi_sector - start_sector
		+ tmp_dev->rdev->data_offset;
	rcu_read_unlock();

	return 1;
}
@@ -381,7 +347,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
static void linear_status (struct seq_file *seq, mddev_t *mddev)
{

	seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
}


+2 −10
Original line number Diff line number Diff line
@@ -3,27 +3,19 @@

struct dev_info {
	mdk_rdev_t	*rdev;
	sector_t	num_sectors;
	sector_t	start_sector;
	sector_t	end_sector;
};

typedef struct dev_info dev_info_t;

struct linear_private_data
{
	struct linear_private_data *prev;	/* earlier version */
	dev_info_t		**hash_table;
	sector_t		spacing;
	sector_t		array_sectors;
	int			sector_shift;	/* shift before dividing
						 * by spacing
						 */
	dev_info_t		disks[0];
	struct rcu_head		rcu;
};


typedef struct linear_private_data linear_conf_t;

#define mddev_to_conf(mddev) ((linear_conf_t *) mddev->private)

#endif
+76 −120
Original line number Diff line number Diff line
@@ -440,15 +440,6 @@ static inline sector_t calc_dev_sboffset(struct block_device *bdev)
	return MD_NEW_SIZE_SECTORS(num_sectors);
}

static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
{
	sector_t num_sectors = rdev->sb_start;

	if (chunk_size)
		num_sectors &= ~((sector_t)chunk_size/512 - 1);
	return num_sectors;
}

static int alloc_disk_sb(mdk_rdev_t * rdev)
{
	if (rdev->sb_page)
@@ -744,6 +735,24 @@ struct super_type {
						sector_t num_sectors);
};

/*
 * Check that the given mddev has no bitmap.
 *
 * This function is called from the run method of all personalities that do not
 * support bitmaps. It prints an error message and returns non-zero if mddev
 * has a bitmap. Otherwise, it returns 0.
 *
 */
int md_check_no_bitmap(mddev_t *mddev)
{
	if (!mddev->bitmap_file && !mddev->bitmap_offset)
		return 0;
	printk(KERN_ERR "%s: bitmaps are not supported for %s\n",
		mdname(mddev), mddev->pers->name);
	return 1;
}
EXPORT_SYMBOL(md_check_no_bitmap);

/*
 * load_super for 0.90.0 
 */
@@ -797,17 +806,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
	rdev->data_offset = 0;
	rdev->sb_size = MD_SB_BYTES;

	if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
		if (sb->level != 1 && sb->level != 4
		    && sb->level != 5 && sb->level != 6
		    && sb->level != 10) {
			/* FIXME use a better test */
			printk(KERN_WARNING
			       "md: bitmaps not supported for this level.\n");
			goto abort;
		}
	}

	if (sb->level == LEVEL_MULTIPATH)
		rdev->desc_nr = -1;
	else
@@ -836,7 +834,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
		else 
			ret = 0;
	}
	rdev->sectors = calc_num_sectors(rdev, sb->chunk_size);
	rdev->sectors = rdev->sb_start;

	if (rdev->sectors < sb->size * 2 && sb->level > 1)
		/* "this cannot possibly happen" ... */
@@ -866,7 +864,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
		mddev->minor_version = sb->minor_version;
		mddev->patch_version = sb->patch_version;
		mddev->external = 0;
		mddev->chunk_size = sb->chunk_size;
		mddev->chunk_sectors = sb->chunk_size >> 9;
		mddev->ctime = sb->ctime;
		mddev->utime = sb->utime;
		mddev->level = sb->level;
@@ -883,13 +881,13 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
			mddev->delta_disks = sb->delta_disks;
			mddev->new_level = sb->new_level;
			mddev->new_layout = sb->new_layout;
			mddev->new_chunk = sb->new_chunk;
			mddev->new_chunk_sectors = sb->new_chunk >> 9;
		} else {
			mddev->reshape_position = MaxSector;
			mddev->delta_disks = 0;
			mddev->new_level = mddev->level;
			mddev->new_layout = mddev->layout;
			mddev->new_chunk = mddev->chunk_size;
			mddev->new_chunk_sectors = mddev->chunk_sectors;
		}

		if (sb->state & (1<<MD_SB_CLEAN))
@@ -1004,7 +1002,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
		sb->new_level = mddev->new_level;
		sb->delta_disks = mddev->delta_disks;
		sb->new_layout = mddev->new_layout;
		sb->new_chunk = mddev->new_chunk;
		sb->new_chunk = mddev->new_chunk_sectors << 9;
	}
	mddev->minor_version = sb->minor_version;
	if (mddev->in_sync)
@@ -1018,7 +1016,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
		sb->recovery_cp = 0;

	sb->layout = mddev->layout;
	sb->chunk_size = mddev->chunk_size;
	sb->chunk_size = mddev->chunk_sectors << 9;

	if (mddev->bitmap && mddev->bitmap_file == NULL)
		sb->state |= (1<<MD_SB_BITMAP_PRESENT);
@@ -1185,17 +1183,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
		       bdevname(rdev->bdev,b));
		return -EINVAL;
	}
	if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
		if (sb->level != cpu_to_le32(1) &&
		    sb->level != cpu_to_le32(4) &&
		    sb->level != cpu_to_le32(5) &&
		    sb->level != cpu_to_le32(6) &&
		    sb->level != cpu_to_le32(10)) {
			printk(KERN_WARNING
			       "md: bitmaps not supported for this level.\n");
			return -EINVAL;
		}
	}

	rdev->preferred_minor = 0xffff;
	rdev->data_offset = le64_to_cpu(sb->data_offset);
@@ -1248,9 +1235,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
	if (rdev->sectors < le64_to_cpu(sb->data_size))
		return -EINVAL;
	rdev->sectors = le64_to_cpu(sb->data_size);
	if (le32_to_cpu(sb->chunksize))
		rdev->sectors &= ~((sector_t)le32_to_cpu(sb->chunksize) - 1);

	if (le64_to_cpu(sb->size) > rdev->sectors)
		return -EINVAL;
	return ret;
@@ -1271,7 +1255,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
		mddev->major_version = 1;
		mddev->patch_version = 0;
		mddev->external = 0;
		mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
		mddev->chunk_sectors = le32_to_cpu(sb->chunksize);
		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
		mddev->level = le32_to_cpu(sb->level);
@@ -1297,13 +1281,13 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
			mddev->delta_disks = le32_to_cpu(sb->delta_disks);
			mddev->new_level = le32_to_cpu(sb->new_level);
			mddev->new_layout = le32_to_cpu(sb->new_layout);
			mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9;
			mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk);
		} else {
			mddev->reshape_position = MaxSector;
			mddev->delta_disks = 0;
			mddev->new_level = mddev->level;
			mddev->new_layout = mddev->layout;
			mddev->new_chunk = mddev->chunk_size;
			mddev->new_chunk_sectors = mddev->chunk_sectors;
		}

	} else if (mddev->pers == NULL) {
@@ -1375,7 +1359,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)

	sb->raid_disks = cpu_to_le32(mddev->raid_disks);
	sb->size = cpu_to_le64(mddev->dev_sectors);
	sb->chunksize = cpu_to_le32(mddev->chunk_size >> 9);
	sb->chunksize = cpu_to_le32(mddev->chunk_sectors);
	sb->level = cpu_to_le32(mddev->level);
	sb->layout = cpu_to_le32(mddev->layout);

@@ -1402,7 +1386,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
		sb->new_layout = cpu_to_le32(mddev->new_layout);
		sb->delta_disks = cpu_to_le32(mddev->delta_disks);
		sb->new_level = cpu_to_le32(mddev->new_level);
		sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9);
		sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
	}

	max_dev = 0;
@@ -1897,6 +1881,7 @@ static void md_update_sb(mddev_t * mddev, int force_change)
	int sync_req;
	int nospares = 0;

	mddev->utime = get_seconds();
	if (mddev->external)
		return;
repeat:
@@ -1926,7 +1911,6 @@ static void md_update_sb(mddev_t * mddev, int force_change)
		nospares = 0;

	sync_req = mddev->in_sync;
	mddev->utime = get_seconds();

	/* If this is just a dirty<->clean transition, and the array is clean
	 * and 'events' is odd, we can roll back to the previous clean state */
@@ -2597,15 +2581,6 @@ static void analyze_sbs(mddev_t * mddev)
			clear_bit(In_sync, &rdev->flags);
		}
	}



	if (mddev->recovery_cp != MaxSector &&
	    mddev->level >= 1)
		printk(KERN_ERR "md: %s: raid array is not clean"
		       " -- starting background reconstruction\n",
		       mdname(mddev));

}

static void md_safemode_timeout(unsigned long data);
@@ -2746,7 +2721,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
	if (IS_ERR(priv)) {
		mddev->new_level = mddev->level;
		mddev->new_layout = mddev->layout;
		mddev->new_chunk = mddev->chunk_size;
		mddev->new_chunk_sectors = mddev->chunk_sectors;
		mddev->raid_disks -= mddev->delta_disks;
		mddev->delta_disks = 0;
		module_put(pers->owner);
@@ -2764,7 +2739,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
	mddev->level = mddev->new_level;
	mddev->layout = mddev->new_layout;
	mddev->chunk_size = mddev->new_chunk;
	mddev->chunk_sectors = mddev->new_chunk_sectors;
	mddev->delta_disks = 0;
	pers->run(mddev);
	mddev_resume(mddev);
@@ -2800,11 +2775,14 @@ layout_store(mddev_t *mddev, const char *buf, size_t len)

	if (mddev->pers) {
		int err;
		if (mddev->pers->reconfig == NULL)
		if (mddev->pers->check_reshape == NULL)
			return -EBUSY;
		err = mddev->pers->reconfig(mddev, n, -1);
		if (err)
		mddev->new_layout = n;
		err = mddev->pers->check_reshape(mddev);
		if (err) {
			mddev->new_layout = mddev->layout;
			return err;
		}
	} else {
		mddev->new_layout = n;
		if (mddev->reshape_position == MaxSector)
@@ -2857,10 +2835,11 @@ static ssize_t
chunk_size_show(mddev_t *mddev, char *page)
{
	if (mddev->reshape_position != MaxSector &&
	    mddev->chunk_size != mddev->new_chunk)
		return sprintf(page, "%d (%d)\n", mddev->new_chunk,
			       mddev->chunk_size);
	return sprintf(page, "%d\n", mddev->chunk_size);
	    mddev->chunk_sectors != mddev->new_chunk_sectors)
		return sprintf(page, "%d (%d)\n",
			       mddev->new_chunk_sectors << 9,
			       mddev->chunk_sectors << 9);
	return sprintf(page, "%d\n", mddev->chunk_sectors << 9);
}

static ssize_t
@@ -2874,15 +2853,18 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)

	if (mddev->pers) {
		int err;
		if (mddev->pers->reconfig == NULL)
		if (mddev->pers->check_reshape == NULL)
			return -EBUSY;
		err = mddev->pers->reconfig(mddev, -1, n);
		if (err)
		mddev->new_chunk_sectors = n >> 9;
		err = mddev->pers->check_reshape(mddev);
		if (err) {
			mddev->new_chunk_sectors = mddev->chunk_sectors;
			return err;
		}
	} else {
		mddev->new_chunk = n;
		mddev->new_chunk_sectors = n >> 9;
		if (mddev->reshape_position == MaxSector)
			mddev->chunk_size = n;
			mddev->chunk_sectors = n >> 9;
	}
	return len;
}
@@ -3527,8 +3509,9 @@ min_sync_store(mddev_t *mddev, const char *buf, size_t len)
		return -EBUSY;

	/* Must be a multiple of chunk_size */
	if (mddev->chunk_size) {
		if (min & (sector_t)((mddev->chunk_size>>9)-1))
	if (mddev->chunk_sectors) {
		sector_t temp = min;
		if (sector_div(temp, mddev->chunk_sectors))
			return -EINVAL;
	}
	mddev->resync_min = min;
@@ -3564,8 +3547,9 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
			return -EBUSY;

		/* Must be a multiple of chunk_size */
		if (mddev->chunk_size) {
			if (max & (sector_t)((mddev->chunk_size>>9)-1))
		if (mddev->chunk_sectors) {
			sector_t temp = max;
			if (sector_div(temp, mddev->chunk_sectors))
				return -EINVAL;
		}
		mddev->resync_max = max;
@@ -3656,7 +3640,7 @@ reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
	mddev->delta_disks = 0;
	mddev->new_level = mddev->level;
	mddev->new_layout = mddev->layout;
	mddev->new_chunk = mddev->chunk_size;
	mddev->new_chunk_sectors = mddev->chunk_sectors;
	return len;
}

@@ -3976,11 +3960,9 @@ static int start_dirty_degraded;
static int do_md_run(mddev_t * mddev)
{
	int err;
	int chunk_size;
	mdk_rdev_t *rdev;
	struct gendisk *disk;
	struct mdk_personality *pers;
	char b[BDEVNAME_SIZE];

	if (list_empty(&mddev->disks))
		/* cannot run an array with no devices.. */
@@ -3998,38 +3980,6 @@ static int do_md_run(mddev_t * mddev)
		analyze_sbs(mddev);
	}

	chunk_size = mddev->chunk_size;

	if (chunk_size) {
		if (chunk_size > MAX_CHUNK_SIZE) {
			printk(KERN_ERR "too big chunk_size: %d > %d\n",
				chunk_size, MAX_CHUNK_SIZE);
			return -EINVAL;
		}
		/*
		 * chunk-size has to be a power of 2
		 */
		if ( (1 << ffz(~chunk_size)) != chunk_size) {
			printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
			return -EINVAL;
		}

		/* devices must have minimum size of one chunk */
		list_for_each_entry(rdev, &mddev->disks, same_set) {
			if (test_bit(Faulty, &rdev->flags))
				continue;
			if (rdev->sectors < chunk_size / 512) {
				printk(KERN_WARNING
					"md: Dev %s smaller than chunk_size:"
					" %llu < %d\n",
					bdevname(rdev->bdev,b),
					(unsigned long long)rdev->sectors,
					chunk_size / 512);
				return -EINVAL;
			}
		}
	}

	if (mddev->level != LEVEL_NONE)
		request_module("md-level-%d", mddev->level);
	else if (mddev->clevel[0])
@@ -4405,7 +4355,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
		mddev->flags = 0;
		mddev->ro = 0;
		mddev->metadata_type[0] = 0;
		mddev->chunk_size = 0;
		mddev->chunk_sectors = 0;
		mddev->ctime = mddev->utime = 0;
		mddev->layout = 0;
		mddev->max_disks = 0;
@@ -4413,7 +4363,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
		mddev->delta_disks = 0;
		mddev->new_level = LEVEL_NONE;
		mddev->new_layout = 0;
		mddev->new_chunk = 0;
		mddev->new_chunk_sectors = 0;
		mddev->curr_resync = 0;
		mddev->resync_mismatches = 0;
		mddev->suspend_lo = mddev->suspend_hi = 0;
@@ -4618,7 +4568,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
	info.spare_disks   = spare;

	info.layout        = mddev->layout;
	info.chunk_size    = mddev->chunk_size;
	info.chunk_size    = mddev->chunk_sectors << 9;

	if (copy_to_user(arg, &info, sizeof(info)))
		return -EFAULT;
@@ -4843,7 +4793,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
			rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
		} else 
			rdev->sb_start = calc_dev_sboffset(rdev->bdev);
		rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
		rdev->sectors = rdev->sb_start;

		err = bind_rdev_to_array(rdev, mddev);
		if (err) {
@@ -4913,7 +4863,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
	else
		rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;

	rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
	rdev->sectors = rdev->sb_start;

	if (test_bit(Faulty, &rdev->flags)) {
		printk(KERN_WARNING 
@@ -5062,7 +5012,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
	mddev->external	     = 0;

	mddev->layout        = info->layout;
	mddev->chunk_size    = info->chunk_size;
	mddev->chunk_sectors = info->chunk_size >> 9;

	mddev->max_disks     = MD_SB_DISKS;

@@ -5081,7 +5031,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
	get_random_bytes(mddev->uuid, 16);

	mddev->new_level = mddev->level;
	mddev->new_chunk = mddev->chunk_size;
	mddev->new_chunk_sectors = mddev->chunk_sectors;
	mddev->new_layout = mddev->layout;
	mddev->delta_disks = 0;

@@ -5191,7 +5141,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
	    mddev->level         != info->level         ||
/*	    mddev->layout        != info->layout        || */
	    !mddev->persistent	 != info->not_persistent||
	    mddev->chunk_size    != info->chunk_size    ||
	    mddev->chunk_sectors != info->chunk_size >> 9 ||
	    /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
	    ((state^info->state) & 0xfffffe00)
		)
@@ -5215,10 +5165,15 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
		 * we don't need to do anything at the md level, the
		 * personality will take care of it all.
		 */
		if (mddev->pers->reconfig == NULL)
		if (mddev->pers->check_reshape == NULL)
			return -EINVAL;
		else
			return mddev->pers->reconfig(mddev, info->layout, -1);
		else {
			mddev->new_layout = info->layout;
			rv = mddev->pers->check_reshape(mddev);
			if (rv)
				mddev->new_layout = mddev->layout;
			return rv;
		}
	}
	if (info->size >= 0 && mddev->dev_sectors / 2 != info->size)
		rv = update_size(mddev, (sector_t)info->size * 2);
@@ -6717,7 +6672,8 @@ void md_check_recovery(mddev_t *mddev)
		 */

		if (mddev->reshape_position != MaxSector) {
			if (mddev->pers->check_reshape(mddev) != 0)
			if (mddev->pers->check_reshape == NULL ||
			    mddev->pers->check_reshape(mddev) != 0)
				/* Cannot proceed */
				goto unlock;
			set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+4 −10

File changed.

Preview size limit exceeded, changes collapsed.

Loading