@@ -225,15 +225,16 @@ static int configfs_dirent_exists(struct configfs_dirent *parent_sd,
225225{
226226 struct configfs_dirent * sd ;
227227
228+ spin_lock (& configfs_dirent_lock );
228229 list_for_each_entry (sd , & parent_sd -> s_children , s_sibling ) {
229230 if (sd -> s_element ) {
230- const unsigned char * existing = configfs_get_name (sd );
231- if (strcmp (existing , new ))
232- continue ;
233- else
231+ if (strcmp (configfs_get_name (sd ), new ) == 0 ) {
232+ spin_unlock (& configfs_dirent_lock );
234233 return - EEXIST ;
234+ }
235235 }
236236 }
237+ spin_unlock (& configfs_dirent_lock );
237238
238239 return 0 ;
239240}
@@ -551,11 +552,28 @@ static void configfs_detach_rollback(struct dentry *dentry)
551552 configfs_detach_rollback (sd -> s_dentry );
552553}
553554
555+ /*
556+ * Find the next non-cursor. configfs_dirent_lock held by caller.
557+ */
558+ static struct configfs_dirent * next_dirent (struct configfs_dirent * parent ,
559+ struct configfs_dirent * last )
560+ {
561+ struct configfs_dirent * s ;
562+
563+ s = list_prepare_entry (last , & parent -> s_children , s_sibling );
564+
565+ list_for_each_entry_continue (s , & parent -> s_children , s_sibling ) {
566+ if (s -> s_element )
567+ return s ;
568+ }
569+ return NULL ;
570+ }
571+
554572static void detach_attrs (struct config_item * item )
555573{
556574 struct dentry * dentry = dget (item -> ci_dentry );
557- struct configfs_dirent * parent_sd ;
558- struct configfs_dirent * sd , * tmp ;
575+ struct configfs_dirent * parent_sd ;
576+ struct configfs_dirent * sd , * next ;
559577
560578 if (!dentry )
561579 return ;
@@ -564,15 +582,19 @@ static void detach_attrs(struct config_item * item)
564582 dentry -> d_name .name );
565583
566584 parent_sd = dentry -> d_fsdata ;
567- list_for_each_entry_safe (sd , tmp , & parent_sd -> s_children , s_sibling ) {
568- if (!sd -> s_element || !(sd -> s_type & CONFIGFS_NOT_PINNED ))
585+
586+ spin_lock (& configfs_dirent_lock );
587+ for (sd = next_dirent (parent_sd , NULL ); sd ; sd = next ) {
588+ next = next_dirent (parent_sd , sd );
589+ if (!(sd -> s_type & CONFIGFS_NOT_PINNED ))
569590 continue ;
570- spin_lock (& configfs_dirent_lock );
571591 list_del_init (& sd -> s_sibling );
572592 spin_unlock (& configfs_dirent_lock );
573593 configfs_drop_dentry (sd , dentry );
574594 configfs_put (sd );
595+ spin_lock (& configfs_dirent_lock );
575596 }
597+ spin_unlock (& configfs_dirent_lock );
576598
577599 /**
578600 * Drop reference from dget() on entrance.
@@ -621,18 +643,20 @@ static void detach_groups(struct config_group *group)
621643 struct dentry * dentry = dget (group -> cg_item .ci_dentry );
622644 struct dentry * child ;
623645 struct configfs_dirent * parent_sd ;
624- struct configfs_dirent * sd , * tmp ;
646+ struct configfs_dirent * sd , * next ;
625647
626648 if (!dentry )
627649 return ;
628650
629651 parent_sd = dentry -> d_fsdata ;
630- list_for_each_entry_safe (sd , tmp , & parent_sd -> s_children , s_sibling ) {
631- if (!sd -> s_element ||
632- !(sd -> s_type & CONFIGFS_USET_DEFAULT ))
652+ spin_lock (& configfs_dirent_lock );
653+ for (sd = next_dirent (parent_sd , NULL ); sd ; sd = next ) {
654+ next = next_dirent (parent_sd , sd );
655+ if (!(sd -> s_type & CONFIGFS_USET_DEFAULT ))
633656 continue ;
634657
635658 child = sd -> s_dentry ;
659+ spin_unlock (& configfs_dirent_lock );
636660
637661 inode_lock (d_inode (child ));
638662
@@ -644,7 +668,9 @@ static void detach_groups(struct config_group *group)
644668
645669 d_delete (child );
646670 dput (child );
671+ spin_lock (& configfs_dirent_lock );
647672 }
673+ spin_unlock (& configfs_dirent_lock );
648674
649675 /**
650676 * Drop reference from dget() on entrance.
@@ -1096,13 +1122,15 @@ configfs_find_subsys_dentry(struct configfs_dirent *root_sd,
10961122 struct configfs_dirent * p ;
10971123 struct configfs_dirent * ret = NULL ;
10981124
1125+ spin_lock (& configfs_dirent_lock );
10991126 list_for_each_entry (p , & root_sd -> s_children , s_sibling ) {
11001127 if (p -> s_type & CONFIGFS_DIR &&
11011128 p -> s_element == subsys_item ) {
11021129 ret = p ;
11031130 break ;
11041131 }
11051132 }
1133+ spin_unlock (& configfs_dirent_lock );
11061134
11071135 return ret ;
11081136}
0 commit comments