Commit 31e5f934 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tracing updates from Steven Rostedt:

 - Remove eventfs_file descriptor

   This is the biggest change, and the second part of making eventfs
   create its files dynamically.

   In 6.6 the first part was added, and that maintained a one to one
   mapping between eventfs meta descriptors and the directories and file
   inodes and dentries that were dynamically created. The directories
   were represented by a eventfs_inode and the files were represented by
   a eventfs_file.

   In v6.7 the eventfs_file is removed. As all events have the same
   directory make up (sched_switch has an "enable", "id", "format", etc
   files), the handing of what files are underneath each leaf eventfs
   directory is moved back to the tracing subsystem via a callback.

   When an event is added to the eventfs, it registers an array of
   evenfs_entry's. These hold the names of the files and the callbacks
   to call when the file is referenced. The callback gets the name so
   that the same callback may be used by multiple files. The callback
   then supplies the filesystem_operations structure needed to create
   this file.

   This has brought the memory footprint of creating multiple eventfs
   instances down by 2 megs each!

 - User events now has persistent events that are not associated to a
   single processes. These are privileged events that hang around even
   if no process is attached to them

 - Clean up of seq_buf

   There's talk about using seq_buf more to replace strscpy() and
   friends. But this also requires some minor modifications of seq_buf
   to be able to do this

 - Expand instance ring buffers individually

   Currently if boot up creates an instance, and a trace event is
   enabled on that instance, the ring buffer for that instance and the
   top level ring buffer are expanded (1.4 MB per CPU). This wastes
   memory as this happens when nothing is using the top level instance

 - Other minor clean ups and fixes

* tag 'trace-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: (34 commits)
  seq_buf: Export seq_buf_puts()
  seq_buf: Export seq_buf_putc()
  eventfs: Use simple_recursive_removal() to clean up dentries
  eventfs: Remove special processing of dput() of events directory
  eventfs: Delete eventfs_inode when the last dentry is freed
  eventfs: Hold eventfs_mutex when calling callback functions
  eventfs: Save ownership and mode
  eventfs: Test for ei->is_freed when accessing ei->dentry
  eventfs: Have a free_ei() that just frees the eventfs_inode
  eventfs: Remove "is_freed" union with rcu head
  eventfs: Fix kerneldoc of eventfs_remove_rec()
  tracing: Have the user copy of synthetic event address use correct context
  eventfs: Remove extra dget() in eventfs_create_events_dir()
  tracing: Have trace_event_file have ref counters
  seq_buf: Introduce DECLARE_SEQ_BUF and seq_buf_str()
  eventfs: Fix typo in eventfs_inode union comment
  eventfs: Fix WARN_ON() in create_file_dentry()
  powerpc: Remove initialisation of readpos
  tracing/histograms: Simplify last_cmd_set()
  seq_buf: fix a misleading comment
  ...
parents fd912e49 70a9affa
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -14,6 +14,11 @@ Programs can view status of the events via
/sys/kernel/tracing/user_events_status and can both register and write
data out via /sys/kernel/tracing/user_events_data.

Programs can also use /sys/kernel/tracing/dynamic_events to register and
delete user based events via the u: prefix. The format of the command to
dynamic_events is the same as the ioctl with the u: prefix applied. This
requires CAP_PERFMON due to the event persisting, otherwise -EPERM is returned.

Typically programs will register a set of events that they wish to expose to
tools that can read trace_events (such as ftrace and perf). The registration
process tells the kernel which address and bit to reflect if any tool has
@@ -45,7 +50,7 @@ This command takes a packed struct user_reg as an argument::
        /* Input: Enable size in bytes at address */
        __u8 enable_size;

        /* Input: Flags for future use, set to 0 */
        /* Input: Flags to use, if any */
        __u16 flags;

        /* Input: Address to update when enabled */
@@ -69,7 +74,7 @@ The struct user_reg requires all the above inputs to be set appropriately.
  This must be 4 (32-bit) or 8 (64-bit). 64-bit values are only allowed to be
  used on 64-bit kernels, however, 32-bit can be used on all kernels.

+ flags: The flags to use, if any. For the initial version this must be 0.
+ flags: The flags to use, if any.
  Callers should first attempt to use flags and retry without flags to ensure
  support for lower versions of the kernel. If a flag is not supported -EINVAL
  is returned.
@@ -80,6 +85,13 @@ The struct user_reg requires all the above inputs to be set appropriately.
+ name_args: The name and arguments to describe the event, see command format
  for details.

The following flags are currently supported.

+ USER_EVENT_REG_PERSIST: The event will not delete upon the last reference
  closing. Callers may use this if an event should exist even after the
  process closes or unregisters the event. Requires CAP_PERFMON otherwise
  -EPERM is returned.

Upon successful registration the following is set.

+ write_index: The index to use for this file descriptor that represents this
@@ -141,7 +153,10 @@ event (in both user and kernel space). User programs should use a separate file
to request deletes than the one used for registration due to this.

**NOTE:** By default events will auto-delete when there are no references left
to the event. Flags in the future may change this logic.
to the event. If programs do not want auto-delete, they must use the
USER_EVENT_REG_PERSIST flag when registering the event. Once that flag is used
the event exists until DIAG_IOCSDEL is invoked. Both register and delete of an
event that persists requires CAP_PERFMON, otherwise -EPERM is returned.

Unregistering
-------------
+0 −1
Original line number Diff line number Diff line
@@ -601,7 +601,6 @@ struct seq_buf ppc_hw_desc __initdata = {
	.buffer = ppc_hw_desc_buf,
	.size = sizeof(ppc_hw_desc_buf),
	.len = 0,
	.readpos = 0,
};

static __init void probe_machine(void)
+634 −459

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode)

	ti = get_tracefs(inode);
	if (ti && ti->flags & TRACEFS_EVENT_INODE)
		eventfs_set_ef_status_free(ti, dentry);
		eventfs_set_ei_status_free(ti, dentry);
	iput(inode);
}

+53 −1
Original line number Diff line number Diff line
@@ -13,6 +13,58 @@ struct tracefs_inode {
	struct inode            vfs_inode;
};

/*
 * struct eventfs_attr - cache the mode and ownership of a eventfs entry
 * @mode:	saved mode plus flags of what is saved
 * @uid:	saved uid if changed
 * @gid:	saved gid if changed
 */
struct eventfs_attr {
	int				mode;
	kuid_t				uid;
	kgid_t				gid;
};

/*
 * struct eventfs_inode - hold the properties of the eventfs directories.
 * @list:	link list into the parent directory
 * @entries:	the array of entries representing the files in the directory
 * @name:	the name of the directory to create
 * @children:	link list into the child eventfs_inode
 * @dentry:     the dentry of the directory
 * @d_parent:   pointer to the parent's dentry
 * @d_children: The array of dentries to represent the files when created
 * @entry_attrs: Saved mode and ownership of the @d_children
 * @attr:	Saved mode and ownership of eventfs_inode itself
 * @data:	The private data to pass to the callbacks
 * @is_freed:	Flag set if the eventfs is on its way to be freed
 *                Note if is_freed is set, then dentry is corrupted.
 * @nr_entries: The number of items in @entries
 */
struct eventfs_inode {
	struct list_head		list;
	const struct eventfs_entry	*entries;
	const char			*name;
	struct list_head		children;
	struct dentry			*dentry; /* Check is_freed to access */
	struct dentry			*d_parent;
	struct dentry			**d_children;
	struct eventfs_attr		*entry_attrs;
	struct eventfs_attr		attr;
	void				*data;
	/*
	 * Union - used for deletion
	 * @llist:	for calling dput() if needed after RCU
	 * @rcu:	eventfs_inode to delete in RCU
	 */
	union {
		struct llist_node	llist;
		struct rcu_head		rcu;
	};
	unsigned int			is_freed:1;
	unsigned int			nr_entries:31;
};

static inline struct tracefs_inode *get_tracefs(const struct inode *inode)
{
	return container_of(inode, struct tracefs_inode, vfs_inode);
@@ -25,6 +77,6 @@ struct inode *tracefs_get_inode(struct super_block *sb);
struct dentry *eventfs_start_creating(const char *name, struct dentry *parent);
struct dentry *eventfs_failed_creating(struct dentry *dentry);
struct dentry *eventfs_end_creating(struct dentry *dentry);
void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry);
void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry);

#endif /* _TRACEFS_INTERNAL_H */
Loading