@@ -207,7 +207,17 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *paren
207
207
return ERR_PTR (- ENOENT );
208
208
}
209
209
sd -> s_frag = get_fragment (frag );
210
- list_add (& sd -> s_sibling , & parent_sd -> s_children );
210
+
211
+ /*
212
+ * configfs_lookup scans only for unpinned items. s_children is
213
+ * partitioned so that configfs_lookup can bail out early.
214
+ * CONFIGFS_PINNED and CONFIGFS_NOT_PINNED are not symmetrical. readdir
215
+ * cursors still need to be inserted at the front of the list.
216
+ */
217
+ if (sd -> s_type & CONFIGFS_PINNED )
218
+ list_add_tail (& sd -> s_sibling , & parent_sd -> s_children );
219
+ else
220
+ list_add (& sd -> s_sibling , & parent_sd -> s_children );
211
221
spin_unlock (& configfs_dirent_lock );
212
222
213
223
return sd ;
@@ -220,10 +230,11 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *paren
220
230
*
221
231
* called with parent inode's i_mutex held
222
232
*/
223
- static int configfs_dirent_exists (struct configfs_dirent * parent_sd ,
224
- const unsigned char * new )
233
+ static int configfs_dirent_exists (struct dentry * dentry )
225
234
{
226
- struct configfs_dirent * sd ;
235
+ struct configfs_dirent * parent_sd = dentry -> d_parent -> d_fsdata ;
236
+ const unsigned char * new = dentry -> d_name .name ;
237
+ struct configfs_dirent * sd ;
227
238
228
239
list_for_each_entry (sd , & parent_sd -> s_children , s_sibling ) {
229
240
if (sd -> s_element ) {
@@ -289,10 +300,6 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry,
289
300
290
301
BUG_ON (!item );
291
302
292
- error = configfs_dirent_exists (p -> d_fsdata , dentry -> d_name .name );
293
- if (unlikely (error ))
294
- return error ;
295
-
296
303
error = configfs_make_dirent (p -> d_fsdata , dentry , item , mode ,
297
304
CONFIGFS_DIR | CONFIGFS_USET_CREATING ,
298
305
frag );
@@ -451,6 +458,18 @@ static struct dentry * configfs_lookup(struct inode *dir,
451
458
452
459
spin_lock (& configfs_dirent_lock );
453
460
list_for_each_entry (sd , & parent_sd -> s_children , s_sibling ) {
461
+
462
+ /*
463
+ * s_children is partitioned, see configfs_new_dirent. The first
464
+ * pinned item indicates we can stop scanning.
465
+ */
466
+ if (sd -> s_type & CONFIGFS_PINNED )
467
+ break ;
468
+
469
+ /*
470
+ * Note: CONFIGFS_PINNED and CONFIGFS_NOT_PINNED are asymmetric.
471
+ * there may be a readdir cursor in this list
472
+ */
454
473
if ((sd -> s_type & CONFIGFS_NOT_PINNED ) &&
455
474
!strcmp (configfs_get_name (sd ), dentry -> d_name .name )) {
456
475
struct configfs_attribute * attr = sd -> s_element ;
@@ -1885,8 +1904,11 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
1885
1904
if (dentry ) {
1886
1905
d_add (dentry , NULL );
1887
1906
1888
- err = configfs_attach_group (sd -> s_element , & group -> cg_item ,
1889
- dentry , frag );
1907
+ err = configfs_dirent_exists (dentry );
1908
+ if (!err )
1909
+ err = configfs_attach_group (sd -> s_element ,
1910
+ & group -> cg_item ,
1911
+ dentry , frag );
1890
1912
if (err ) {
1891
1913
BUG_ON (d_inode (dentry ));
1892
1914
d_drop (dentry );
0 commit comments