Skip to content

Commit 0eb03c7

Browse files
committed
Merge tag 'trace-tracefs-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracefs/eventfs updates from Steven Rostedt: "Bug fixes: - The eventfs directories need to have unique inode numbers. Make sure that they do not get the default file inode number. - Update the inode uid and gid fields on remount. When a remount happens where a uid and/or gid is specified, all the tracefs files and directories should get the specified uid and/or gid. But this can be sporadic when some uids were assigned already. There's already a list of inodes that are allocated. Just update their uid and gid fields at the time of remount. - Update the eventfs_inodes on remount from the top level "events" descriptor. There was a bug where not all the eventfs files or directories where getting updated on remount. One fix was to clear the SAVED_UID/GID flags from the inode list during the iteration of the inodes during the remount. But because the eventfs inodes can be freed when the last referenced is released, not all the eventfs_inodes were being updated. This lead to the ownership selftest to fail if it was run a second time (the first time would leave eventfs_inodes with no corresponding tracefs_inode). Instead, for eventfs_inodes, only process the "events" eventfs_inode from the list iteration, as it is guaranteed to have a tracefs_inode (it's never freed while the "events" directory exists). As it has a list of its children, and the children have a list of their children, just iterate all the eventfs_inodes from the "events" descriptor and it is guaranteed to get all of them. - Clear the EVENT_INODE flag from the tracefs_drop_inode() callback. Currently the EVENTFS_INODE FLAG is cleared in the tracefs_d_iput() callback. But this is the wrong location. The iput() callback is called when the last reference to the dentry inode is hit. There could be a case where two dentry's have the same inode, and the flag will be cleared prematurely. The flag needs to be cleared when the last reference of the inode is dropped and that happens in the inode's drop_inode() callback handler. Cleanups: - Consolidate the creation of a tracefs_inode for an eventfs_inode A tracefs_inode is created for both files and directories of the eventfs system. It is open coded. Instead, consolidate it into a single eventfs_get_inode() function call. - Remove the eventfs getattr and permission callbacks. The permissions for the eventfs files and directories are updated when the inodes are created, on remount, and when the user sets them (via setattr). The inodes hold the current permissions so there is no need to have custom getattr or permissions callbacks as they will more likely cause them to be incorrect. The inode's permissions are updated when they should be updated. Remove the getattr and permissions inode callbacks. - Do not update eventfs_inode attributes on creation of inodes. The eventfs_inodes attribute field is used to store the permissions of the directories and files for when their corresponding inodes are freed and are created again. But when the creation of the inodes happen, the eventfs_inode attributes are recalculated. The recalculation should only happen when the permissions change for a given file or directory. Currently, the attribute changes are just being set to their current files so this is not a bug, but it's unnecessary and error prone. Stop doing that. - The events directory inode is created once when the events directory is created and deleted when it is deleted. It is now updated on remount and when the user changes the permissions. There's no need to use the eventfs_inode of the events directory to store the events directory permissions. But using it to store the default permissions for the files within the directory that have not been updated by the user can simplify the code" * tag 'trace-tracefs-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: eventfs: Do not use attributes for events directory eventfs: Cleanup permissions in creation of inodes eventfs: Remove getattr and permission callbacks eventfs: Consolidate the eventfs_inode update in eventfs_get_inode() tracefs: Clear EVENT_INODE flag in tracefs_drop_inode() eventfs: Update all the eventfs_inodes from the events descriptor tracefs: Update inode permissions on remount eventfs: Keep the directories from having the same inode number as files
2 parents 6d69b6c + 2dd00ac commit 0eb03c7

File tree

2 files changed

+116
-155
lines changed

2 files changed

+116
-155
lines changed

fs/tracefs/event_inode.c

Lines changed: 87 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ static DEFINE_MUTEX(eventfs_mutex);
3737

3838
struct eventfs_root_inode {
3939
struct eventfs_inode ei;
40-
struct inode *parent_inode;
4140
struct dentry *events_dir;
4241
};
4342

@@ -50,8 +49,12 @@ static struct eventfs_root_inode *get_root_inode(struct eventfs_inode *ei)
5049
/* Just try to make something consistent and unique */
5150
static int eventfs_dir_ino(struct eventfs_inode *ei)
5251
{
53-
if (!ei->ino)
52+
if (!ei->ino) {
5453
ei->ino = get_next_ino();
54+
/* Must not have the file inode number */
55+
if (ei->ino == EVENTFS_FILE_INODE_INO)
56+
ei->ino = get_next_ino();
57+
}
5558

5659
return ei->ino;
5760
}
@@ -207,7 +210,9 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
207210
* determined by the parent directory.
208211
*/
209212
if (dentry->d_inode->i_mode & S_IFDIR) {
210-
update_attr(&ei->attr, iattr);
213+
/* Just use the inode permissions for the events directory */
214+
if (!ei->is_events)
215+
update_attr(&ei->attr, iattr);
211216

212217
} else {
213218
name = dentry->d_name.name;
@@ -225,70 +230,9 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
225230
return ret;
226231
}
227232

228-
static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb)
229-
{
230-
struct eventfs_root_inode *rei;
231-
struct inode *parent;
232-
233-
rei = get_root_inode(ei);
234-
235-
/* Use the parent inode permissions unless root set its permissions */
236-
parent = rei->parent_inode;
237-
238-
if (rei->ei.attr.mode & EVENTFS_SAVE_UID)
239-
ei->attr.uid = rei->ei.attr.uid;
240-
else
241-
ei->attr.uid = parent->i_uid;
242-
243-
if (rei->ei.attr.mode & EVENTFS_SAVE_GID)
244-
ei->attr.gid = rei->ei.attr.gid;
245-
else
246-
ei->attr.gid = parent->i_gid;
247-
}
248-
249-
static void set_top_events_ownership(struct inode *inode)
250-
{
251-
struct tracefs_inode *ti = get_tracefs(inode);
252-
struct eventfs_inode *ei = ti->private;
253-
254-
/* The top events directory doesn't get automatically updated */
255-
if (!ei || !ei->is_events)
256-
return;
257-
258-
update_events_attr(ei, inode->i_sb);
259-
260-
if (!(ei->attr.mode & EVENTFS_SAVE_UID))
261-
inode->i_uid = ei->attr.uid;
262-
263-
if (!(ei->attr.mode & EVENTFS_SAVE_GID))
264-
inode->i_gid = ei->attr.gid;
265-
}
266-
267-
static int eventfs_get_attr(struct mnt_idmap *idmap,
268-
const struct path *path, struct kstat *stat,
269-
u32 request_mask, unsigned int flags)
270-
{
271-
struct dentry *dentry = path->dentry;
272-
struct inode *inode = d_backing_inode(dentry);
273-
274-
set_top_events_ownership(inode);
275-
276-
generic_fillattr(idmap, request_mask, inode, stat);
277-
return 0;
278-
}
279-
280-
static int eventfs_permission(struct mnt_idmap *idmap,
281-
struct inode *inode, int mask)
282-
{
283-
set_top_events_ownership(inode);
284-
return generic_permission(idmap, inode, mask);
285-
}
286-
287233
static const struct inode_operations eventfs_dir_inode_operations = {
288234
.lookup = eventfs_root_lookup,
289235
.setattr = eventfs_set_attr,
290-
.getattr = eventfs_get_attr,
291-
.permission = eventfs_permission,
292236
};
293237

294238
static const struct inode_operations eventfs_file_inode_operations = {
@@ -301,84 +245,109 @@ static const struct file_operations eventfs_file_operations = {
301245
.llseek = generic_file_llseek,
302246
};
303247

304-
/*
305-
* On a remount of tracefs, if UID or GID options are set, then
306-
* the mount point inode permissions should be used.
307-
* Reset the saved permission flags appropriately.
308-
*/
309-
void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
248+
static void eventfs_set_attrs(struct eventfs_inode *ei, bool update_uid, kuid_t uid,
249+
bool update_gid, kgid_t gid, int level)
310250
{
311-
struct eventfs_inode *ei = ti->private;
251+
struct eventfs_inode *ei_child;
312252

313-
if (!ei)
253+
/* Update events/<system>/<event> */
254+
if (WARN_ON_ONCE(level > 3))
314255
return;
315256

316-
if (update_uid)
257+
if (update_uid) {
317258
ei->attr.mode &= ~EVENTFS_SAVE_UID;
259+
ei->attr.uid = uid;
260+
}
318261

319-
if (update_gid)
262+
if (update_gid) {
320263
ei->attr.mode &= ~EVENTFS_SAVE_GID;
264+
ei->attr.gid = gid;
265+
}
266+
267+
list_for_each_entry(ei_child, &ei->children, list) {
268+
eventfs_set_attrs(ei_child, update_uid, uid, update_gid, gid, level + 1);
269+
}
321270

322271
if (!ei->entry_attrs)
323272
return;
324273

325274
for (int i = 0; i < ei->nr_entries; i++) {
326-
if (update_uid)
275+
if (update_uid) {
327276
ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID;
328-
if (update_gid)
277+
ei->entry_attrs[i].uid = uid;
278+
}
279+
if (update_gid) {
329280
ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID;
281+
ei->entry_attrs[i].gid = gid;
282+
}
330283
}
284+
331285
}
332286

333-
/* Return the evenfs_inode of the "events" directory */
334-
static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
287+
/*
288+
* On a remount of tracefs, if UID or GID options are set, then
289+
* the mount point inode permissions should be used.
290+
* Reset the saved permission flags appropriately.
291+
*/
292+
void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
335293
{
336-
struct eventfs_inode *ei;
294+
struct eventfs_inode *ei = ti->private;
337295

338-
do {
339-
// The parent is stable because we do not do renames
340-
dentry = dentry->d_parent;
341-
// ... and directories always have d_fsdata
342-
ei = dentry->d_fsdata;
296+
/* Only the events directory does the updates */
297+
if (!ei || !ei->is_events || ei->is_freed)
298+
return;
343299

344-
/*
345-
* If the ei is being freed, the ownership of the children
346-
* doesn't matter.
347-
*/
348-
if (ei->is_freed)
349-
return NULL;
300+
eventfs_set_attrs(ei, update_uid, ti->vfs_inode.i_uid,
301+
update_gid, ti->vfs_inode.i_gid, 0);
302+
}
350303

351-
// Walk upwards until you find the events inode
352-
} while (!ei->is_events);
304+
static void update_inode_attr(struct inode *inode, umode_t mode,
305+
struct eventfs_attr *attr, struct eventfs_root_inode *rei)
306+
{
307+
if (attr && attr->mode & EVENTFS_SAVE_MODE)
308+
inode->i_mode = attr->mode & EVENTFS_MODE_MASK;
309+
else
310+
inode->i_mode = mode;
353311

354-
update_events_attr(ei, dentry->d_sb);
312+
if (attr && attr->mode & EVENTFS_SAVE_UID)
313+
inode->i_uid = attr->uid;
314+
else
315+
inode->i_uid = rei->ei.attr.uid;
355316

356-
return ei;
317+
if (attr && attr->mode & EVENTFS_SAVE_GID)
318+
inode->i_gid = attr->gid;
319+
else
320+
inode->i_gid = rei->ei.attr.gid;
357321
}
358322

359-
static void update_inode_attr(struct dentry *dentry, struct inode *inode,
360-
struct eventfs_attr *attr, umode_t mode)
323+
static struct inode *eventfs_get_inode(struct dentry *dentry, struct eventfs_attr *attr,
324+
umode_t mode, struct eventfs_inode *ei)
361325
{
362-
struct eventfs_inode *events_ei = eventfs_find_events(dentry);
326+
struct eventfs_root_inode *rei;
327+
struct eventfs_inode *pei;
328+
struct tracefs_inode *ti;
329+
struct inode *inode;
363330

364-
if (!events_ei)
365-
return;
331+
inode = tracefs_get_inode(dentry->d_sb);
332+
if (!inode)
333+
return NULL;
366334

367-
inode->i_mode = mode;
368-
inode->i_uid = events_ei->attr.uid;
369-
inode->i_gid = events_ei->attr.gid;
335+
ti = get_tracefs(inode);
336+
ti->private = ei;
337+
ti->flags |= TRACEFS_EVENT_INODE;
370338

371-
if (!attr)
372-
return;
339+
/* Find the top dentry that holds the "events" directory */
340+
do {
341+
dentry = dentry->d_parent;
342+
/* Directories always have d_fsdata */
343+
pei = dentry->d_fsdata;
344+
} while (!pei->is_events);
373345

374-
if (attr->mode & EVENTFS_SAVE_MODE)
375-
inode->i_mode = attr->mode & EVENTFS_MODE_MASK;
346+
rei = get_root_inode(pei);
376347

377-
if (attr->mode & EVENTFS_SAVE_UID)
378-
inode->i_uid = attr->uid;
348+
update_inode_attr(inode, mode, attr, rei);
379349

380-
if (attr->mode & EVENTFS_SAVE_GID)
381-
inode->i_gid = attr->gid;
350+
return inode;
382351
}
383352

384353
/**
@@ -401,7 +370,6 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,
401370
void *data,
402371
const struct file_operations *fop)
403372
{
404-
struct tracefs_inode *ti;
405373
struct inode *inode;
406374

407375
if (!(mode & S_IFMT))
@@ -410,23 +378,18 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,
410378
if (WARN_ON_ONCE(!S_ISREG(mode)))
411379
return ERR_PTR(-EIO);
412380

413-
inode = tracefs_get_inode(dentry->d_sb);
381+
/* Only directories have ti->private set to an ei, not files */
382+
inode = eventfs_get_inode(dentry, attr, mode, NULL);
414383
if (unlikely(!inode))
415384
return ERR_PTR(-ENOMEM);
416385

417-
/* If the user updated the directory's attributes, use them */
418-
update_inode_attr(dentry, inode, attr, mode);
419-
420386
inode->i_op = &eventfs_file_inode_operations;
421387
inode->i_fop = fop;
422388
inode->i_private = data;
423389

424390
/* All files will have the same inode number */
425391
inode->i_ino = EVENTFS_FILE_INODE_INO;
426392

427-
ti = get_tracefs(inode);
428-
ti->flags |= TRACEFS_EVENT_INODE;
429-
430393
// Files have their parent's ei as their fsdata
431394
dentry->d_fsdata = get_ei(parent_ei);
432395

@@ -446,28 +409,19 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,
446409
static struct dentry *lookup_dir_entry(struct dentry *dentry,
447410
struct eventfs_inode *pei, struct eventfs_inode *ei)
448411
{
449-
struct tracefs_inode *ti;
450412
struct inode *inode;
413+
umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
451414

452-
inode = tracefs_get_inode(dentry->d_sb);
415+
inode = eventfs_get_inode(dentry, &ei->attr, mode, ei);
453416
if (unlikely(!inode))
454417
return ERR_PTR(-ENOMEM);
455418

456-
/* If the user updated the directory's attributes, use them */
457-
update_inode_attr(dentry, inode, &ei->attr,
458-
S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
459-
460419
inode->i_op = &eventfs_dir_inode_operations;
461420
inode->i_fop = &eventfs_file_operations;
462421

463422
/* All directories will have the same inode number */
464423
inode->i_ino = eventfs_dir_ino(ei);
465424

466-
ti = get_tracefs(inode);
467-
ti->flags |= TRACEFS_EVENT_INODE;
468-
/* Only directories have ti->private set to an ei, not files */
469-
ti->private = ei;
470-
471425
dentry->d_fsdata = get_ei(ei);
472426

473427
d_add(dentry, inode);
@@ -828,7 +782,6 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
828782
// Note: we have a ref to the dentry from tracefs_start_creating()
829783
rei = get_root_inode(ei);
830784
rei->events_dir = dentry;
831-
rei->parent_inode = d_inode(dentry->d_sb->s_root);
832785

833786
ei->entries = entries;
834787
ei->nr_entries = size;
@@ -838,14 +791,12 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
838791
uid = d_inode(dentry->d_parent)->i_uid;
839792
gid = d_inode(dentry->d_parent)->i_gid;
840793

841-
ei->attr.uid = uid;
842-
ei->attr.gid = gid;
843-
844794
/*
845-
* When the "events" directory is created, it takes on the
846-
* permissions of its parent. But can be reset on remount.
795+
* The ei->attr will be used as the default values for the
796+
* files beneath this directory.
847797
*/
848-
ei->attr.mode |= EVENTFS_SAVE_UID | EVENTFS_SAVE_GID;
798+
ei->attr.uid = uid;
799+
ei->attr.gid = gid;
849800

850801
INIT_LIST_HEAD(&ei->children);
851802
INIT_LIST_HEAD(&ei->list);

0 commit comments

Comments
 (0)