Skip to content

Commit 49304c2

Browse files
torvaldsrostedt
authored andcommitted
tracefs: dentry lookup crapectomy
The dentry lookup for eventfs files was very broken, and had lots of signs of the old situation where the filesystem names were all created statically in the dentry tree, rather than being looked up dynamically based on the eventfs data structures. You could see it in the naming - how it claimed to "create" dentries rather than just look up the dentries that were given it. You could see it in various nonsensical and very incorrect operations, like using "simple_lookup()" on the dentries that were passed in, which only results in those dentries becoming negative dentries. Which meant that any other lookup would possibly return ENOENT if it saw that negative dentry before the data was then later filled in. You could see it in the immense amount of nonsensical code that didn't actually just do lookups. Link: https://lore.kernel.org/linux-trace-kernel/[email protected]/ Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Cc: [email protected] Cc: Al Viro <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Ajay Kaher <[email protected]> Cc: Mark Rutland <[email protected]> Fixes: c1504e5 ("eventfs: Implement eventfs dir creation functions") Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 99c001c commit 49304c2

File tree

3 files changed

+50
-297
lines changed

3 files changed

+50
-297
lines changed

fs/tracefs/event_inode.c

Lines changed: 50 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
230230
{
231231
struct eventfs_inode *ei;
232232

233-
mutex_lock(&eventfs_mutex);
234233
do {
235234
// The parent is stable because we do not do renames
236235
dentry = dentry->d_parent;
@@ -247,7 +246,6 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
247246
}
248247
// Walk upwards until you find the events inode
249248
} while (!ei->is_events);
250-
mutex_unlock(&eventfs_mutex);
251249

252250
update_top_events_attr(ei, dentry->d_sb);
253251

@@ -280,25 +278,24 @@ static void update_inode_attr(struct dentry *dentry, struct inode *inode,
280278
}
281279

282280
/**
283-
* create_file - create a file in the tracefs filesystem
284-
* @name: the name of the file to create.
281+
* lookup_file - look up a file in the tracefs filesystem
282+
* @dentry: the dentry to look up
285283
* @mode: the permission that the file should have.
286284
* @attr: saved attributes changed by user
287-
* @parent: parent dentry for this file.
288285
* @data: something that the caller will want to get to later on.
289286
* @fop: struct file_operations that should be used for this file.
290287
*
291288
* This function creates a dentry that represents a file in the eventsfs_inode
292289
* directory. The inode.i_private pointer will point to @data in the open()
293290
* call.
294291
*/
295-
static struct dentry *create_file(const char *name, umode_t mode,
292+
static struct dentry *lookup_file(struct dentry *dentry,
293+
umode_t mode,
296294
struct eventfs_attr *attr,
297-
struct dentry *parent, void *data,
295+
void *data,
298296
const struct file_operations *fop)
299297
{
300298
struct tracefs_inode *ti;
301-
struct dentry *dentry;
302299
struct inode *inode;
303300

304301
if (!(mode & S_IFMT))
@@ -307,15 +304,9 @@ static struct dentry *create_file(const char *name, umode_t mode,
307304
if (WARN_ON_ONCE(!S_ISREG(mode)))
308305
return NULL;
309306

310-
WARN_ON_ONCE(!parent);
311-
dentry = eventfs_start_creating(name, parent);
312-
313-
if (IS_ERR(dentry))
314-
return dentry;
315-
316307
inode = tracefs_get_inode(dentry->d_sb);
317308
if (unlikely(!inode))
318-
return eventfs_failed_creating(dentry);
309+
return ERR_PTR(-ENOMEM);
319310

320311
/* If the user updated the directory's attributes, use them */
321312
update_inode_attr(dentry, inode, attr, mode);
@@ -329,32 +320,29 @@ static struct dentry *create_file(const char *name, umode_t mode,
329320

330321
ti = get_tracefs(inode);
331322
ti->flags |= TRACEFS_EVENT_INODE;
332-
d_instantiate(dentry, inode);
323+
324+
d_add(dentry, inode);
333325
fsnotify_create(dentry->d_parent->d_inode, dentry);
334-
return eventfs_end_creating(dentry);
326+
return dentry;
335327
};
336328

337329
/**
338-
* create_dir - create a dir in the tracefs filesystem
330+
* lookup_dir_entry - look up a dir in the tracefs filesystem
331+
* @dentry: the directory to look up
339332
* @ei: the eventfs_inode that represents the directory to create
340-
* @parent: parent dentry for this file.
341333
*
342-
* This function will create a dentry for a directory represented by
334+
* This function will look up a dentry for a directory represented by
343335
* a eventfs_inode.
344336
*/
345-
static struct dentry *create_dir(struct eventfs_inode *ei, struct dentry *parent)
337+
static struct dentry *lookup_dir_entry(struct dentry *dentry,
338+
struct eventfs_inode *pei, struct eventfs_inode *ei)
346339
{
347340
struct tracefs_inode *ti;
348-
struct dentry *dentry;
349341
struct inode *inode;
350342

351-
dentry = eventfs_start_creating(ei->name, parent);
352-
if (IS_ERR(dentry))
353-
return dentry;
354-
355343
inode = tracefs_get_inode(dentry->d_sb);
356344
if (unlikely(!inode))
357-
return eventfs_failed_creating(dentry);
345+
return ERR_PTR(-ENOMEM);
358346

359347
/* If the user updated the directory's attributes, use them */
360348
update_inode_attr(dentry, inode, &ei->attr,
@@ -371,11 +359,14 @@ static struct dentry *create_dir(struct eventfs_inode *ei, struct dentry *parent
371359
/* Only directories have ti->private set to an ei, not files */
372360
ti->private = ei;
373361

362+
dentry->d_fsdata = ei;
363+
ei->dentry = dentry; // Remove me!
364+
374365
inc_nlink(inode);
375-
d_instantiate(dentry, inode);
366+
d_add(dentry, inode);
376367
inc_nlink(dentry->d_parent->d_inode);
377368
fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
378-
return eventfs_end_creating(dentry);
369+
return dentry;
379370
}
380371

381372
static void free_ei(struct eventfs_inode *ei)
@@ -425,7 +416,7 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
425416
}
426417

427418
/**
428-
* create_file_dentry - create a dentry for a file of an eventfs_inode
419+
* lookup_file_dentry - create a dentry for a file of an eventfs_inode
429420
* @ei: the eventfs_inode that the file will be created under
430421
* @idx: the index into the d_children[] of the @ei
431422
* @parent: The parent dentry of the created file.
@@ -438,157 +429,21 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
438429
* address located at @e_dentry.
439430
*/
440431
static struct dentry *
441-
create_file_dentry(struct eventfs_inode *ei, int idx,
442-
struct dentry *parent, const char *name, umode_t mode, void *data,
432+
lookup_file_dentry(struct dentry *dentry,
433+
struct eventfs_inode *ei, int idx,
434+
umode_t mode, void *data,
443435
const struct file_operations *fops)
444436
{
445437
struct eventfs_attr *attr = NULL;
446438
struct dentry **e_dentry = &ei->d_children[idx];
447-
struct dentry *dentry;
448-
449-
WARN_ON_ONCE(!inode_is_locked(parent->d_inode));
450439

451-
mutex_lock(&eventfs_mutex);
452-
if (ei->is_freed) {
453-
mutex_unlock(&eventfs_mutex);
454-
return NULL;
455-
}
456-
/* If the e_dentry already has a dentry, use it */
457-
if (*e_dentry) {
458-
dget(*e_dentry);
459-
mutex_unlock(&eventfs_mutex);
460-
return *e_dentry;
461-
}
462-
463-
/* ei->entry_attrs are protected by SRCU */
464440
if (ei->entry_attrs)
465441
attr = &ei->entry_attrs[idx];
466442

467-
mutex_unlock(&eventfs_mutex);
468-
469-
dentry = create_file(name, mode, attr, parent, data, fops);
443+
dentry->d_fsdata = ei; // NOTE: ei of _parent_
444+
lookup_file(dentry, mode, attr, data, fops);
470445

471-
mutex_lock(&eventfs_mutex);
472-
473-
if (IS_ERR_OR_NULL(dentry)) {
474-
/*
475-
* When the mutex was released, something else could have
476-
* created the dentry for this e_dentry. In which case
477-
* use that one.
478-
*
479-
* If ei->is_freed is set, the e_dentry is currently on its
480-
* way to being freed, don't return it. If e_dentry is NULL
481-
* it means it was already freed.
482-
*/
483-
if (ei->is_freed) {
484-
dentry = NULL;
485-
} else {
486-
dentry = *e_dentry;
487-
dget(dentry);
488-
}
489-
mutex_unlock(&eventfs_mutex);
490-
return dentry;
491-
}
492-
493-
if (!*e_dentry && !ei->is_freed) {
494-
*e_dentry = dentry;
495-
dentry->d_fsdata = ei;
496-
} else {
497-
/*
498-
* Should never happen unless we get here due to being freed.
499-
* Otherwise it means two dentries exist with the same name.
500-
*/
501-
WARN_ON_ONCE(!ei->is_freed);
502-
dentry = NULL;
503-
}
504-
mutex_unlock(&eventfs_mutex);
505-
506-
return dentry;
507-
}
508-
509-
/**
510-
* eventfs_post_create_dir - post create dir routine
511-
* @ei: eventfs_inode of recently created dir
512-
*
513-
* Map the meta-data of files within an eventfs dir to their parent dentry
514-
*/
515-
static void eventfs_post_create_dir(struct eventfs_inode *ei)
516-
{
517-
struct eventfs_inode *ei_child;
518-
519-
lockdep_assert_held(&eventfs_mutex);
520-
521-
/* srcu lock already held */
522-
/* fill parent-child relation */
523-
list_for_each_entry_srcu(ei_child, &ei->children, list,
524-
srcu_read_lock_held(&eventfs_srcu)) {
525-
ei_child->d_parent = ei->dentry;
526-
}
527-
}
528-
529-
/**
530-
* create_dir_dentry - Create a directory dentry for the eventfs_inode
531-
* @pei: The eventfs_inode parent of ei.
532-
* @ei: The eventfs_inode to create the directory for
533-
* @parent: The dentry of the parent of this directory
534-
*
535-
* This creates and attaches a directory dentry to the eventfs_inode @ei.
536-
*/
537-
static struct dentry *
538-
create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
539-
struct dentry *parent)
540-
{
541-
struct dentry *dentry = NULL;
542-
543-
WARN_ON_ONCE(!inode_is_locked(parent->d_inode));
544-
545-
mutex_lock(&eventfs_mutex);
546-
if (pei->is_freed || ei->is_freed) {
547-
mutex_unlock(&eventfs_mutex);
548-
return NULL;
549-
}
550-
if (ei->dentry) {
551-
/* If the eventfs_inode already has a dentry, use it */
552-
dentry = ei->dentry;
553-
dget(dentry);
554-
mutex_unlock(&eventfs_mutex);
555-
return dentry;
556-
}
557-
mutex_unlock(&eventfs_mutex);
558-
559-
dentry = create_dir(ei, parent);
560-
561-
mutex_lock(&eventfs_mutex);
562-
563-
if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) {
564-
/*
565-
* When the mutex was released, something else could have
566-
* created the dentry for this e_dentry. In which case
567-
* use that one.
568-
*
569-
* If ei->is_freed is set, the e_dentry is currently on its
570-
* way to being freed.
571-
*/
572-
dentry = ei->dentry;
573-
if (dentry)
574-
dget(dentry);
575-
mutex_unlock(&eventfs_mutex);
576-
return dentry;
577-
}
578-
579-
if (!ei->dentry && !ei->is_freed) {
580-
ei->dentry = dentry;
581-
eventfs_post_create_dir(ei);
582-
dentry->d_fsdata = ei;
583-
} else {
584-
/*
585-
* Should never happen unless we get here due to being freed.
586-
* Otherwise it means two dentries exist with the same name.
587-
*/
588-
WARN_ON_ONCE(!ei->is_freed);
589-
dentry = NULL;
590-
}
591-
mutex_unlock(&eventfs_mutex);
446+
*e_dentry = dentry; // Remove me
592447

593448
return dentry;
594449
}
@@ -607,79 +462,49 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
607462
struct dentry *dentry,
608463
unsigned int flags)
609464
{
610-
const struct file_operations *fops;
611-
const struct eventfs_entry *entry;
612465
struct eventfs_inode *ei_child;
613466
struct tracefs_inode *ti;
614467
struct eventfs_inode *ei;
615-
struct dentry *ei_dentry = NULL;
616-
struct dentry *ret = NULL;
617-
struct dentry *d;
618468
const char *name = dentry->d_name.name;
619-
umode_t mode;
620-
void *data;
621-
int idx;
622-
int i;
623-
int r;
624469

625470
ti = get_tracefs(dir);
626471
if (!(ti->flags & TRACEFS_EVENT_INODE))
627-
return NULL;
628-
629-
/* Grab srcu to prevent the ei from going away */
630-
idx = srcu_read_lock(&eventfs_srcu);
472+
return ERR_PTR(-EIO);
631473

632-
/*
633-
* Grab the eventfs_mutex to consistent value from ti->private.
634-
* This s
635-
*/
636474
mutex_lock(&eventfs_mutex);
637-
ei = READ_ONCE(ti->private);
638-
if (ei && !ei->is_freed)
639-
ei_dentry = READ_ONCE(ei->dentry);
640-
mutex_unlock(&eventfs_mutex);
641475

642-
if (!ei || !ei_dentry)
476+
ei = ti->private;
477+
if (!ei || ei->is_freed)
643478
goto out;
644479

645-
data = ei->data;
646-
647-
list_for_each_entry_srcu(ei_child, &ei->children, list,
648-
srcu_read_lock_held(&eventfs_srcu)) {
480+
list_for_each_entry(ei_child, &ei->children, list) {
649481
if (strcmp(ei_child->name, name) != 0)
650482
continue;
651-
ret = simple_lookup(dir, dentry, flags);
652-
if (IS_ERR(ret))
483+
if (ei_child->is_freed)
653484
goto out;
654-
d = create_dir_dentry(ei, ei_child, ei_dentry);
655-
dput(d);
485+
lookup_dir_entry(dentry, ei, ei_child);
656486
goto out;
657487
}
658488

659-
for (i = 0; i < ei->nr_entries; i++) {
660-
entry = &ei->entries[i];
661-
if (strcmp(name, entry->name) == 0) {
662-
void *cdata = data;
663-
mutex_lock(&eventfs_mutex);
664-
/* If ei->is_freed, then the event itself may be too */
665-
if (!ei->is_freed)
666-
r = entry->callback(name, &mode, &cdata, &fops);
667-
else
668-
r = -1;
669-
mutex_unlock(&eventfs_mutex);
670-
if (r <= 0)
671-
continue;
672-
ret = simple_lookup(dir, dentry, flags);
673-
if (IS_ERR(ret))
674-
goto out;
675-
d = create_file_dentry(ei, i, ei_dentry, name, mode, cdata, fops);
676-
dput(d);
677-
break;
678-
}
489+
for (int i = 0; i < ei->nr_entries; i++) {
490+
void *data;
491+
umode_t mode;
492+
const struct file_operations *fops;
493+
const struct eventfs_entry *entry = &ei->entries[i];
494+
495+
if (strcmp(name, entry->name) != 0)
496+
continue;
497+
498+
data = ei->data;
499+
if (entry->callback(name, &mode, &data, &fops) <= 0)
500+
goto out;
501+
502+
lookup_file_dentry(dentry, ei, i, mode, data, fops);
503+
goto out;
679504
}
680505
out:
681-
srcu_read_unlock(&eventfs_srcu, idx);
682-
return ret;
506+
mutex_unlock(&eventfs_mutex);
507+
return NULL;
683508
}
684509

685510
/*

0 commit comments

Comments
 (0)