mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-30 05:11:01 +00:00 
			
		
		
		
	 e93f68a1fc
			
		
	
	
		e93f68a1fc
		
	
	
	
	
		
			
			Most array level changes leave the list of devices largely unchanged, possibly causing one at the end to become redundant. However conversions between RAID0 and RAID10 need to renumber all devices (except 0). This renumbering is currently being done in the ->run method when the new personality takes over. However this is too late as the common code in md.c might already have invalidated some of the devices if they had a ->raid_disk number that appeared to high. Moving it into the ->takeover method is too early as the array is still active at that time and wrong ->raid_disk numbers could cause confusion. So add a ->new_raid_disk field to mdk_rdev_s and use it to communicate the new raid_disk number. Now the common code knows exactly which devices need to be renumbered, and which can be invalidated, and can do it all at a convenient time when the array is suspend. It can also update some symlinks in sysfs which previously were not be updated correctly. Reported-by: Maciej Trela <maciej.trela@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef _RAID10_H
 | |
| #define _RAID10_H
 | |
| 
 | |
| typedef struct mirror_info mirror_info_t;
 | |
| 
 | |
| struct mirror_info {
 | |
| 	mdk_rdev_t	*rdev;
 | |
| 	sector_t	head_position;
 | |
| };
 | |
| 
 | |
| typedef struct r10bio_s r10bio_t;
 | |
| 
 | |
| struct r10_private_data_s {
 | |
| 	mddev_t			*mddev;
 | |
| 	mirror_info_t		*mirrors;
 | |
| 	int			raid_disks;
 | |
| 	spinlock_t		device_lock;
 | |
| 
 | |
| 	/* geometry */
 | |
| 	int			near_copies;  /* number of copies layed out raid0 style */
 | |
| 	int 			far_copies;   /* number of copies layed out
 | |
| 					       * at large strides across drives
 | |
| 					       */
 | |
| 	int			far_offset;   /* far_copies are offset by 1 stripe
 | |
| 					       * instead of many
 | |
| 					       */
 | |
| 	int			copies;	      /* near_copies * far_copies.
 | |
| 					       * must be <= raid_disks
 | |
| 					       */
 | |
| 	sector_t		stride;	      /* distance between far copies.
 | |
| 					       * This is size / far_copies unless
 | |
| 					       * far_offset, in which case it is
 | |
| 					       * 1 stripe.
 | |
| 					       */
 | |
| 
 | |
| 	sector_t		dev_sectors;  /* temp copy of mddev->dev_sectors */
 | |
| 
 | |
| 	int chunk_shift; /* shift from chunks to sectors */
 | |
| 	sector_t chunk_mask;
 | |
| 
 | |
| 	struct list_head	retry_list;
 | |
| 	/* queue pending writes and submit them on unplug */
 | |
| 	struct bio_list		pending_bio_list;
 | |
| 
 | |
| 
 | |
| 	spinlock_t		resync_lock;
 | |
| 	int nr_pending;
 | |
| 	int nr_waiting;
 | |
| 	int nr_queued;
 | |
| 	int barrier;
 | |
| 	sector_t		next_resync;
 | |
| 	int			fullsync;  /* set to 1 if a full sync is needed,
 | |
| 					    * (fresh device added).
 | |
| 					    * Cleared when a sync completes.
 | |
| 					    */
 | |
| 
 | |
| 	wait_queue_head_t	wait_barrier;
 | |
| 
 | |
| 	mempool_t *r10bio_pool;
 | |
| 	mempool_t *r10buf_pool;
 | |
| 	struct page		*tmppage;
 | |
| 
 | |
| 	/* When taking over an array from a different personality, we store
 | |
| 	 * the new thread here until we fully activate the array.
 | |
| 	 */
 | |
| 	struct mdk_thread_s	*thread;
 | |
| };
 | |
| 
 | |
| typedef struct r10_private_data_s conf_t;
 | |
| 
 | |
| /*
 | |
|  * this is our 'private' RAID10 bio.
 | |
|  *
 | |
|  * it contains information about what kind of IO operations were started
 | |
|  * for this RAID10 operation, and about their status:
 | |
|  */
 | |
| 
 | |
| struct r10bio_s {
 | |
| 	atomic_t		remaining; /* 'have we finished' count,
 | |
| 					    * used from IRQ handlers
 | |
| 					    */
 | |
| 	sector_t		sector;	/* virtual sector number */
 | |
| 	int			sectors;
 | |
| 	unsigned long		state;
 | |
| 	mddev_t			*mddev;
 | |
| 	/*
 | |
| 	 * original bio going to /dev/mdx
 | |
| 	 */
 | |
| 	struct bio		*master_bio;
 | |
| 	/*
 | |
| 	 * if the IO is in READ direction, then this is where we read
 | |
| 	 */
 | |
| 	int			read_slot;
 | |
| 
 | |
| 	struct list_head	retry_list;
 | |
| 	/*
 | |
| 	 * if the IO is in WRITE direction, then multiple bios are used,
 | |
| 	 * one for each copy.
 | |
| 	 * When resyncing we also use one for each copy.
 | |
| 	 * When reconstructing, we use 2 bios, one for read, one for write.
 | |
| 	 * We choose the number when they are allocated.
 | |
| 	 */
 | |
| 	struct {
 | |
| 		struct bio		*bio;
 | |
| 		sector_t addr;
 | |
| 		int devnum;
 | |
| 	} devs[0];
 | |
| };
 | |
| 
 | |
| /* when we get a read error on a read-only array, we redirect to another
 | |
|  * device without failing the first device, or trying to over-write to
 | |
|  * correct the read error.  To keep track of bad blocks on a per-bio
 | |
|  * level, we store IO_BLOCKED in the appropriate 'bios' pointer
 | |
|  */
 | |
| #define IO_BLOCKED ((struct bio*)1)
 | |
| 
 | |
| /* bits for r10bio.state */
 | |
| #define	R10BIO_Uptodate	0
 | |
| #define	R10BIO_IsSync	1
 | |
| #define	R10BIO_IsRecover 2
 | |
| #define	R10BIO_Degraded 3
 | |
| #endif
 |