@@ -711,6 +711,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
711711 */
712712 int i ;
713713 int active = 0 , working = 0 ,failed = 0 ,spare = 0 ,nr_disks = 0 ;
714+ unsigned int fixdesc = 0 ;
714715
715716 rdev -> sb_size = MD_SB_BYTES ;
716717
@@ -758,16 +759,28 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
758759 sb -> disks [0 ].state = (1 <<MD_DISK_REMOVED );
759760 ITERATE_RDEV (mddev ,rdev2 ,tmp ) {
760761 mdp_disk_t * d ;
762+ int desc_nr ;
761763 if (rdev2 -> raid_disk >= 0 && rdev2 -> in_sync && !rdev2 -> faulty )
762- rdev2 -> desc_nr = rdev2 -> raid_disk ;
764+ desc_nr = rdev2 -> raid_disk ;
763765 else
764- rdev2 -> desc_nr = next_spare ++ ;
766+ desc_nr = next_spare ++ ;
767+ if (desc_nr != rdev2 -> desc_nr ) {
768+ fixdesc |= (1 << desc_nr );
769+ rdev2 -> desc_nr = desc_nr ;
770+ if (rdev2 -> raid_disk >= 0 ) {
771+ char nm [20 ];
772+ sprintf (nm , "rd%d" , rdev2 -> raid_disk );
773+ sysfs_remove_link (& mddev -> kobj , nm );
774+ }
775+ sysfs_remove_link (& rdev2 -> kobj , "block" );
776+ kobject_del (& rdev2 -> kobj );
777+ }
765778 d = & sb -> disks [rdev2 -> desc_nr ];
766779 nr_disks ++ ;
767780 d -> number = rdev2 -> desc_nr ;
768781 d -> major = MAJOR (rdev2 -> bdev -> bd_dev );
769782 d -> minor = MINOR (rdev2 -> bdev -> bd_dev );
770- if (rdev2 -> raid_disk >= 0 && rdev -> in_sync && !rdev2 -> faulty )
783+ if (rdev2 -> raid_disk >= 0 && rdev2 -> in_sync && !rdev2 -> faulty )
771784 d -> raid_disk = rdev2 -> raid_disk ;
772785 else
773786 d -> raid_disk = rdev2 -> desc_nr ; /* compatibility */
@@ -787,7 +800,22 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
787800 if (test_bit (WriteMostly , & rdev2 -> flags ))
788801 d -> state |= (1 <<MD_DISK_WRITEMOSTLY );
789802 }
790-
803+ if (fixdesc )
804+ ITERATE_RDEV (mddev ,rdev2 ,tmp )
805+ if (fixdesc & (1 <<rdev2 -> desc_nr )) {
806+ snprintf (rdev2 -> kobj .name , KOBJ_NAME_LEN , "dev%d" ,
807+ rdev2 -> desc_nr );
808+ kobject_add (& rdev2 -> kobj );
809+ sysfs_create_link (& rdev2 -> kobj ,
810+ & rdev2 -> bdev -> bd_disk -> kobj ,
811+ "block" );
812+ if (rdev2 -> raid_disk >= 0 ) {
813+ char nm [20 ];
814+ sprintf (nm , "rd%d" , rdev2 -> raid_disk );
815+ sysfs_create_link (& mddev -> kobj ,
816+ & rdev2 -> kobj , nm );
817+ }
818+ }
791819 /* now set the "removed" and "faulty" bits on any missing devices */
792820 for (i = 0 ; i < mddev -> raid_disks ; i ++ ) {
793821 mdp_disk_t * d = & sb -> disks [i ];
@@ -1147,6 +1175,13 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
11471175 list_add (& rdev -> same_set , & mddev -> disks );
11481176 rdev -> mddev = mddev ;
11491177 printk (KERN_INFO "md: bind<%s>\n" , bdevname (rdev -> bdev ,b ));
1178+
1179+ rdev -> kobj .k_name = NULL ;
1180+ snprintf (rdev -> kobj .name , KOBJ_NAME_LEN , "dev%d" , rdev -> desc_nr );
1181+ rdev -> kobj .parent = kobject_get (& mddev -> kobj );
1182+ kobject_add (& rdev -> kobj );
1183+
1184+ sysfs_create_link (& rdev -> kobj , & rdev -> bdev -> bd_disk -> kobj , "block" );
11501185 return 0 ;
11511186}
11521187
@@ -1160,6 +1195,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
11601195 list_del_init (& rdev -> same_set );
11611196 printk (KERN_INFO "md: unbind<%s>\n" , bdevname (rdev -> bdev ,b ));
11621197 rdev -> mddev = NULL ;
1198+ sysfs_remove_link (& rdev -> kobj , "block" );
1199+ kobject_del (& rdev -> kobj );
11631200}
11641201
11651202/*
@@ -1215,7 +1252,7 @@ static void export_rdev(mdk_rdev_t * rdev)
12151252 md_autodetect_dev (rdev -> bdev -> bd_dev );
12161253#endif
12171254 unlock_rdev (rdev );
1218- kfree ( rdev );
1255+ kobject_put ( & rdev -> kobj );
12191256}
12201257
12211258static void kick_rdev_from_array (mdk_rdev_t * rdev )
@@ -1414,6 +1451,94 @@ static void md_update_sb(mddev_t * mddev)
14141451
14151452}
14161453
1454+ struct rdev_sysfs_entry {
1455+ struct attribute attr ;
1456+ ssize_t (* show )(mdk_rdev_t * , char * );
1457+ ssize_t (* store )(mdk_rdev_t * , const char * , size_t );
1458+ };
1459+
1460+ static ssize_t
1461+ rdev_show_state (mdk_rdev_t * rdev , char * page )
1462+ {
1463+ char * sep = "" ;
1464+ int len = 0 ;
1465+
1466+ if (rdev -> faulty ) {
1467+ len += sprintf (page + len , "%sfaulty" ,sep );
1468+ sep = "," ;
1469+ }
1470+ if (rdev -> in_sync ) {
1471+ len += sprintf (page + len , "%sin_sync" ,sep );
1472+ sep = "," ;
1473+ }
1474+ if (!rdev -> faulty && !rdev -> in_sync ) {
1475+ len += sprintf (page + len , "%sspare" , sep );
1476+ sep = "," ;
1477+ }
1478+ return len + sprintf (page + len , "\n" );
1479+ }
1480+
1481+ static struct rdev_sysfs_entry rdev_state = {
1482+ .attr = {.name = "state" , .mode = S_IRUGO },
1483+ .show = rdev_show_state ,
1484+ };
1485+
1486+ static ssize_t
1487+ rdev_show_super (mdk_rdev_t * rdev , char * page )
1488+ {
1489+ if (rdev -> sb_loaded && rdev -> sb_size ) {
1490+ memcpy (page , page_address (rdev -> sb_page ), rdev -> sb_size );
1491+ return rdev -> sb_size ;
1492+ } else
1493+ return 0 ;
1494+ }
1495+ static struct rdev_sysfs_entry rdev_super = {
1496+ .attr = {.name = "super" , .mode = S_IRUGO },
1497+ .show = rdev_show_super ,
1498+ };
1499+ static struct attribute * rdev_default_attrs [] = {
1500+ & rdev_state .attr ,
1501+ & rdev_super .attr ,
1502+ NULL ,
1503+ };
1504+ static ssize_t
1505+ rdev_attr_show (struct kobject * kobj , struct attribute * attr , char * page )
1506+ {
1507+ struct rdev_sysfs_entry * entry = container_of (attr , struct rdev_sysfs_entry , attr );
1508+ mdk_rdev_t * rdev = container_of (kobj , mdk_rdev_t , kobj );
1509+
1510+ if (!entry -> show )
1511+ return - EIO ;
1512+ return entry -> show (rdev , page );
1513+ }
1514+
1515+ static ssize_t
1516+ rdev_attr_store (struct kobject * kobj , struct attribute * attr ,
1517+ const char * page , size_t length )
1518+ {
1519+ struct rdev_sysfs_entry * entry = container_of (attr , struct rdev_sysfs_entry , attr );
1520+ mdk_rdev_t * rdev = container_of (kobj , mdk_rdev_t , kobj );
1521+
1522+ if (!entry -> store )
1523+ return - EIO ;
1524+ return entry -> store (rdev , page , length );
1525+ }
1526+
1527+ static void rdev_free (struct kobject * ko )
1528+ {
1529+ mdk_rdev_t * rdev = container_of (ko , mdk_rdev_t , kobj );
1530+ kfree (rdev );
1531+ }
1532+ static struct sysfs_ops rdev_sysfs_ops = {
1533+ .show = rdev_attr_show ,
1534+ .store = rdev_attr_store ,
1535+ };
1536+ static struct kobj_type rdev_ktype = {
1537+ .release = rdev_free ,
1538+ .sysfs_ops = & rdev_sysfs_ops ,
1539+ .default_attrs = rdev_default_attrs ,
1540+ };
1541+
14171542/*
14181543 * Import a device. If 'super_format' >= 0, then sanity check the superblock
14191544 *
@@ -1445,6 +1570,10 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
14451570 if (err )
14461571 goto abort_free ;
14471572
1573+ rdev -> kobj .parent = NULL ;
1574+ rdev -> kobj .ktype = & rdev_ktype ;
1575+ kobject_init (& rdev -> kobj );
1576+
14481577 rdev -> desc_nr = -1 ;
14491578 rdev -> faulty = 0 ;
14501579 rdev -> in_sync = 0 ;
@@ -1820,6 +1949,13 @@ static int do_md_run(mddev_t * mddev)
18201949 mddev -> safemode_timer .data = (unsigned long ) mddev ;
18211950 mddev -> safemode_delay = (20 * HZ )/1000 + 1 ; /* 20 msec delay */
18221951 mddev -> in_sync = 1 ;
1952+
1953+ ITERATE_RDEV (mddev ,rdev ,tmp )
1954+ if (rdev -> raid_disk >= 0 ) {
1955+ char nm [20 ];
1956+ sprintf (nm , "rd%d" , rdev -> raid_disk );
1957+ sysfs_create_link (& mddev -> kobj , & rdev -> kobj , nm );
1958+ }
18231959
18241960 set_bit (MD_RECOVERY_NEEDED , & mddev -> recovery );
18251961 md_wakeup_thread (mddev -> thread );
@@ -1941,9 +2077,18 @@ static int do_md_stop(mddev_t * mddev, int ro)
19412077 * Free resources if final stop
19422078 */
19432079 if (!ro ) {
2080+ mdk_rdev_t * rdev ;
2081+ struct list_head * tmp ;
19442082 struct gendisk * disk ;
19452083 printk (KERN_INFO "md: %s stopped.\n" , mdname (mddev ));
19462084
2085+ ITERATE_RDEV (mddev ,rdev ,tmp )
2086+ if (rdev -> raid_disk >= 0 ) {
2087+ char nm [20 ];
2088+ sprintf (nm , "rd%d" , rdev -> raid_disk );
2089+ sysfs_remove_link (& mddev -> kobj , nm );
2090+ }
2091+
19472092 export_array (mddev );
19482093
19492094 mddev -> array_size = 0 ;
@@ -3962,17 +4107,24 @@ void md_check_recovery(mddev_t *mddev)
39624107 if (rdev -> raid_disk >= 0 &&
39634108 (rdev -> faulty || ! rdev -> in_sync ) &&
39644109 atomic_read (& rdev -> nr_pending )== 0 ) {
3965- if (mddev -> pers -> hot_remove_disk (mddev , rdev -> raid_disk )== 0 )
4110+ if (mddev -> pers -> hot_remove_disk (mddev , rdev -> raid_disk )== 0 ) {
4111+ char nm [20 ];
4112+ sprintf (nm ,"rd%d" , rdev -> raid_disk );
4113+ sysfs_remove_link (& mddev -> kobj , nm );
39664114 rdev -> raid_disk = -1 ;
4115+ }
39674116 }
39684117
39694118 if (mddev -> degraded ) {
39704119 ITERATE_RDEV (mddev ,rdev ,rtmp )
39714120 if (rdev -> raid_disk < 0
39724121 && !rdev -> faulty ) {
3973- if (mddev -> pers -> hot_add_disk (mddev ,rdev ))
4122+ if (mddev -> pers -> hot_add_disk (mddev ,rdev )) {
4123+ char nm [20 ];
4124+ sprintf (nm , "rd%d" , rdev -> raid_disk );
4125+ sysfs_create_link (& mddev -> kobj , & rdev -> kobj , nm );
39744126 spares ++ ;
3975- else
4127+ } else
39764128 break ;
39774129 }
39784130 }
0 commit comments