Accessing the device ID of get_task_exe_file() at task exit (for extending procstats)
Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Accessing the device ID of get_task_exe_file() at task exit (for extending procstats)
Hi,
I'm trying to write an extension to the taskstats interface to give me the program executable belonging to a process on exit. Basically, I want the contents of the /proc/$pid/exe link.
I figured an efficient way to achieve this would be to give the device ID and inode of the file. This works for the inode, but the device is alwasy zero. I guess I am not accessing the correct data or I am doing it at a time where it is not valid anymore.
The relevant bit is this change:
Code:
diff --git a/include/uapi/linux/taskstats.h b/include/uapi/linux/taskstats.h
index b7aa7bb2349f..56b4a67f035c 100644
--- a/include/uapi/linux/taskstats.h
+++ b/include/uapi/linux/taskstats.h
@@ -34,7 +34,7 @@
*/
-#define TASKSTATS_VERSION 8
+#define TASKSTATS_VERSION 9
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */
@@ -164,6 +164,24 @@ struct taskstats {
/* Delay waiting for memory reclaim */
__u64 freepages_count;
__u64 freepages_delay_total;
+
+ /*
+ * Version 9:
+ * Extra fields detailing executable file (/proc/$pid/exe).
+ * Values are both zero if there is no executable file
+ * Chose 64 bit for both to keep alignment. Only 32 bit expected
+ * for device, while userspace will usually only use 16 anyway.
+ * The client application is supposed to translate that to a
+ * file path itself, with knowledge about possible failure
+ * modes (changes in mounts, filesystem operations).
+ * Communicating the path from the kernel's view would mean
+ * adding PATH_MAX bytes to this struct and more work.
+ * I guess we do not want that. It would be convenient, though.
+ */
+ __u64 ac_exe_dev; /* device ID */
+ __u64 ac_exe_inode; /* inode number */
+ /* Version 9 ends here. */
+
};
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 4e62a4a8fa91..0f589acd95cd 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -166,6 +166,20 @@ static void send_cpu_listeners(struct sk_buff *skb,
up_write(&listeners->sem);
}
+static void exe_add_tsk(struct taskstats *stats, struct task_struct *tsk)
+{
+ /* No idea if I'm allowed to access that here, now. */
+ struct file *exe_file = get_task_exe_file(tsk);
+ if (exe_file) {
+ stats->ac_exe_dev = new_encode_dev(exe_file->f_inode->i_rdev);
+ stats->ac_exe_inode = exe_file->f_inode->i_ino;
+ fput(exe_file);
+ } else {
+ stats->ac_exe_dev = 0;
+ stats->ac_exe_inode = 0;
+ }
+}
+
static void fill_stats(struct user_namespace *user_ns,
struct pid_namespace *pid_ns,
struct task_struct *tsk, struct taskstats *stats)
@@ -188,6 +202,9 @@ static void fill_stats(struct user_namespace *user_ns,
/* fill in extended acct fields */
xacct_add_tsk(stats, tsk);
+
+ /* add executable info */
+ exe_add_tsk(stats, tsk);
}
static int fill_stats_for_pid(pid_t pid, struct taskstats *stats)
The resulting device number is always zero. Any idea how I could access it at this point in process life? Do I need to fetch it earlier?
I'm especially confused between i_rdev and i_bdev … these details about when what data in a struct inode has meaning are not that explicitly documented. You either know or you don't;-) Hints?
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524
Rep:
So, taskstats returns the exiting program's PID but not the program name? What's this: /* Basic Accounting Fields start */
char ac_comm[TS_COMM_LEN]; /* Command name */.
Thanks for your response, but sadly, that's not what I need. The commad field does not tell you which executable was behind the process. It tells you that the process wants to tell you that the executed command is foo, which does not even have to correlate with the actual binary. When you run
Code:
bash some_script.sh
bash will put some_script.sh into the command field. Maybe python does the same. In that case, I'm not interested in which script the user ran, but that the interpreter binary used resources. Also, since we have several versions of the same software installed, the path-less command name will not tell them apart. If you run a program foo, the command field will say foo, not /opt/foo/1.2.3/bin/foo.
Actually, I'd like the full path to the program binary. My idea was to do that via a device identifier and the inode as a space-efficient way to communicate equivalent information.
/proc/PID/exe is exactly what I am after. The issue is: I want to get a stream of that when processes exit. If I have to poll /proc for processes appearing, I will always miss short-lived ones. I want full statistics. I actually went to BSD process accounting first, then realized that there is taskstats as a more powerful and extensible system.
I actually looked at how /proc/PID/exe comes to be and took the hint which variable to access to get at the executable file. I just got stuck at only getting the inode, not the device. I might try if I can reconstruct the path the same way the proc code does it and at least printk it, or actually return in a temporary hack in a grossly enlarged taskstats struct. That would confirm that the information is still there (just not where I look right now).
But I very much doubt a patch growing the taskstats struct by PATH_MAX+1 bytes would be accepted.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.