@@ -888,16 +888,37 @@ struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev)
888888}
889889EXPORT_SYMBOL_GPL (md_find_rdev_rcu );
890890
891- static struct md_personality * find_pers (int level , char * clevel )
891+ static struct md_personality * get_pers (int level , char * clevel )
892892{
893+ struct md_personality * ret = NULL ;
893894 struct md_personality * pers ;
895+
896+ spin_lock (& pers_lock );
894897 list_for_each_entry (pers , & pers_list , list ) {
895- if (level != LEVEL_NONE && pers -> level == level )
896- return pers ;
897- if (strcmp (pers -> name , clevel )== 0 )
898- return pers ;
898+ if ((level != LEVEL_NONE && pers -> level == level ) ||
899+ !strcmp (pers -> name , clevel )) {
900+ if (try_module_get (pers -> owner ))
901+ ret = pers ;
902+ break ;
903+ }
899904 }
900- return NULL ;
905+ spin_unlock (& pers_lock );
906+
907+ if (!ret ) {
908+ if (level != LEVEL_NONE )
909+ pr_warn ("md: personality for level %d is not loaded!\n" ,
910+ level );
911+ else
912+ pr_warn ("md: personality for level %s is not loaded!\n" ,
913+ clevel );
914+ }
915+
916+ return ret ;
917+ }
918+
919+ static void put_pers (struct md_personality * pers )
920+ {
921+ module_put (pers -> owner );
901922}
902923
903924/* return the offset of the super block in 512byte sectors */
@@ -3931,24 +3952,20 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
39313952
39323953 if (request_module ("md-%s" , clevel ) != 0 )
39333954 request_module ("md-level-%s" , clevel );
3934- spin_lock (& pers_lock );
3935- pers = find_pers (level , clevel );
3936- if (!pers || !try_module_get (pers -> owner )) {
3937- spin_unlock (& pers_lock );
3938- pr_warn ("md: personality %s not loaded\n" , clevel );
3955+ pers = get_pers (level , clevel );
3956+ if (!pers ) {
39393957 rv = - EINVAL ;
39403958 goto out_unlock ;
39413959 }
3942- spin_unlock (& pers_lock );
39433960
39443961 if (pers == mddev -> pers ) {
39453962 /* Nothing to do! */
3946- module_put (pers -> owner );
3963+ put_pers (pers );
39473964 rv = len ;
39483965 goto out_unlock ;
39493966 }
39503967 if (!pers -> takeover ) {
3951- module_put (pers -> owner );
3968+ put_pers (pers );
39523969 pr_warn ("md: %s: %s does not support personality takeover\n" ,
39533970 mdname (mddev ), clevel );
39543971 rv = - EINVAL ;
@@ -3969,7 +3986,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
39693986 mddev -> raid_disks -= mddev -> delta_disks ;
39703987 mddev -> delta_disks = 0 ;
39713988 mddev -> reshape_backwards = 0 ;
3972- module_put (pers -> owner );
3989+ put_pers (pers );
39733990 pr_warn ("md: %s: %s would not accept array\n" ,
39743991 mdname (mddev ), clevel );
39753992 rv = PTR_ERR (priv );
@@ -4026,7 +4043,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
40264043 mddev -> to_remove = & md_redundancy_group ;
40274044 }
40284045
4029- module_put (oldpers -> owner );
4046+ put_pers (oldpers );
40304047
40314048 rdev_for_each (rdev , mddev ) {
40324049 if (rdev -> raid_disk < 0 )
@@ -6096,20 +6113,11 @@ int md_run(struct mddev *mddev)
60966113 goto exit_sync_set ;
60976114 }
60986115
6099- spin_lock (& pers_lock );
6100- pers = find_pers (mddev -> level , mddev -> clevel );
6101- if (!pers || !try_module_get (pers -> owner )) {
6102- spin_unlock (& pers_lock );
6103- if (mddev -> level != LEVEL_NONE )
6104- pr_warn ("md: personality for level %d is not loaded!\n" ,
6105- mddev -> level );
6106- else
6107- pr_warn ("md: personality for level %s is not loaded!\n" ,
6108- mddev -> clevel );
6116+ pers = get_pers (mddev -> level , mddev -> clevel );
6117+ if (!pers ) {
61096118 err = - EINVAL ;
61106119 goto abort ;
61116120 }
6112- spin_unlock (& pers_lock );
61136121 if (mddev -> level != pers -> level ) {
61146122 mddev -> level = pers -> level ;
61156123 mddev -> new_level = pers -> level ;
@@ -6119,7 +6127,7 @@ int md_run(struct mddev *mddev)
61196127 if (mddev -> reshape_position != MaxSector &&
61206128 pers -> start_reshape == NULL ) {
61216129 /* This personality cannot handle reshaping... */
6122- module_put (pers -> owner );
6130+ put_pers (pers );
61236131 err = - EINVAL ;
61246132 goto abort ;
61256133 }
@@ -6246,7 +6254,7 @@ int md_run(struct mddev *mddev)
62466254 if (mddev -> private )
62476255 pers -> free (mddev , mddev -> private );
62486256 mddev -> private = NULL ;
6249- module_put (pers -> owner );
6257+ put_pers (pers );
62506258 mddev -> bitmap_ops -> destroy (mddev );
62516259abort :
62526260 bioset_exit (& mddev -> io_clone_set );
@@ -6467,7 +6475,7 @@ static void __md_stop(struct mddev *mddev)
64676475 mddev -> private = NULL ;
64686476 if (pers -> sync_request && mddev -> to_remove == NULL )
64696477 mddev -> to_remove = & md_redundancy_group ;
6470- module_put (pers -> owner );
6478+ put_pers (pers );
64716479 clear_bit (MD_RECOVERY_FROZEN , & mddev -> recovery );
64726480
64736481 bioset_exit (& mddev -> bio_set );
0 commit comments