It contains the following functions:
</para>
!Itapset/errno.stp
+ </chapter>
+ <chapter id="rlimit.stp">
+ <title>RLIMIT Tapset</title>
+ <para>
+ This set of functions is used to handle string which defines resource limits (RLIMIT_*) and returns
+ corresponding number of resource limit.
+ It contains the following functions:
+ </para>
+!Itapset/rlimit.stp
</chapter>
<chapter id="dev.stp">
<title>Device Tapset</title>
--- /dev/null
+%{
+#include <linux/version.h>
+%}
+
+/**
+ * sfunction rlimit_from_str - Symbolic string associated with resource limit code
+ *
+ * @lim_str: The string representation of limit
+ *
+ * Description: This function returns the number associated
+ * with the given string, such as 0 for the string RLIMIT_CPU, or
+ * -1 for an out-of-range value.
+ */
+function rlimit_from_str:long (lim_str:string)
+%{ /* pure */
+ char *lim_str = (char *)(long)STAP_ARG_lim_str;
+
+#define aux_rlimit(limit_arg) \
+ if (strncmp(lim_str, #limit_arg, MAXSTRINGLEN) == 0) { \
+ STAP_RETVALUE = limit_arg; \
+ return; \
+ }
+
+ /* Little kernel history digging */
+ /* This set is stable from 2.6.1 kernel version */
+ aux_rlimit(RLIMIT_CPU);
+ aux_rlimit(RLIMIT_FSIZE);
+ aux_rlimit(RLIMIT_DATA);
+ aux_rlimit(RLIMIT_STACK);
+ aux_rlimit(RLIMIT_CORE);
+ aux_rlimit(RLIMIT_RSS);
+ aux_rlimit(RLIMIT_NPROC);
+ aux_rlimit(RLIMIT_NOFILE);
+ aux_rlimit(RLIMIT_MEMLOCK);
+ aux_rlimit(RLIMIT_AS);
+ aux_rlimit(RLIMIT_LOCKS);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
+ aux_rlimit(RLIMIT_SIGPENDING);
+ aux_rlimit(RLIMIT_MSGQUEUE);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
+ aux_rlimit(RLIMIT_NICE);
+ aux_rlimit(RLIMIT_RTPRIO);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
+ aux_rlimit(RLIMIT_RTTIME);
+#endif
+
+ STAP_RETVALUE = -1;
+
+#undef aux_rlimit
+%}
STAP_RETVALUE = (long)current;
%}
+function _task_rlimit_cur:long (task:long, nd_limit:long)
+{
+ if (nd_limit < 0 || nd_limit >= %{ RLIM_NLIMITS %}) {
+ return -1;
+ }
+ sig = @cast(task, "task_struct", "kernel<linux/sched.h>")->signal;
+ rlimit = @cast(sig, "signal_struct", "kernel<linux/sched.h>")->rlim;
+ return @cast(rlimit, "rlimit", "kernel<linux/sched.h>")[nd_limit]->rlim_cur;
+}
+
+/* sfunction task_rlimit - The current resource limit of the tash
+ *
+ * @task: task_struct pointer
+ * @lim_str: String representing limit.
+ *
+ * Description: Little bit slower way how ger resource limits of
+ * process.
+ * There is need translate string into number for each call.
+ */
+function task_rlimit:long (task:long, lim_str:string)
+{
+ lim = rlimit_from_str(lim_str);
+ if (lim == -1) { return -1; }
+ return _task_rlimit_cur(task, lim);
+}
+
+/* Fast and "safe" way how to do it. */
+
+function task_rlimit_cpu:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_CPU %} );
+}
+
+function task_rlimit_fsize:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_FSIZE %});
+}
+
+function task_rlimit_data:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_DATA %});
+}
+
+function task_rlimit_stack:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_STACK %});
+}
+
+function task_rlimit_core:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_CORE %});
+}
+
+function task_rlimit_rss:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_RSS %});
+}
+
+function task_rlimit_nproc:long (task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_NPROC %});
+}
+
+function task_rlimit_nofile:long(task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_NOFILE %});
+}
+
+function task_rlimit_memlock:long(task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_MEMLOCK %});
+}
+
+function task_rlimit_as:long(task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_AS %});
+}
+
+function task_rlimit_locks:long(task:long)
+{
+ return _task_rlimit_cur(task, %{ RLIMIT_LOCKS %});
+}
+
+function task_rlimit_sigpending:long(task:long)
+{
+ %( kernel_v >= "2.6.8" %?
+ return _task_rlimit_cur(task, %{ RLIMIT_SIGPENDING %});
+ %:
+ return -1
+ %)
+}
+
+function task_rlimit_msgqueue:long(task:long)
+{
+ %( kernel_v >= "2.6.8" %?
+ return _task_rlimit_cur(task, %{ RLIMIT_MSGQUEUE %});
+ %:
+ return -1
+ %)
+}
+
+function task_rlimit_nice:long(task:long)
+{
+ %( kernel_v >= "2.6.12" %?
+ return _task_rlimit_cur(task, %{ RLIMIT_NICE %});
+ %:
+ return -1
+ %)
+}
+
+function task_rlimit_rtprio:long(task:long)
+{
+ %( kernel_v >= "2.6.12" %?
+ return _task_rlimit_cur(task, %{ RLIMIT_RTPRIO %});
+ %:
+ return -1
+ %)
+}
+
+function task_rlimit_rttime:long(task:long)
+{
+ %( kernel_v >= "2.6.25" %?
+ return _task_rlimit_cur(task, %{ RLIMIT_RTTIME %});
+ %:
+ return -1
+ %)
+}
+
/**
* sfunction task_parent - The task_struct of the parent task
*
--- /dev/null
+probe begin
+{
+ print (task_rlimit_cpu(0) +
+ task_rlimit_fsize(0) +
+ task_rlimit_data(0) +
+ task_rlimit_stack(0) +
+ task_rlimit_core(0) +
+ task_rlimit_rss(0) +
+ task_rlimit_nproc(0) +
+ task_rlimit_nofile(0) +
+ task_rlimit_memlock(0) +
+ task_rlimit_as(0) +
+ task_rlimit_locks(0) +
+ task_rlimit_sigpending(0) +
+ task_rlimit_msgqueue(0) +
+ task_rlimit_nice(0) +
+ task_rlimit_rtprio(0) +
+ task_rlimit_rttime(0) +
+ rlimit_from_str(""));
+}
--- /dev/null
+title: Trace processes running out of file descriptors
+name: rlimit_nofile.stp
+keywords: limits
+subsystem: process
+description: This script watches processes being scheduled and which try to allocate a file descriptor without luck.
+test_check: stap -p4 rlimit_nofile.stp
+test_installcheck: stap rlimit_nofile.stp -c "sleep 0.2"
--- /dev/null
+############################################################
+# rlimit_nofile.stp
+# Author: Robin Hack <rhack@redhat.com>
+# This script watches processes being scheduled and which
+# try to allocate a file descriptor without luck.
+############################################################
+
+global failed_calls
+
+probe kernel.trace("sched_wakeup")
+{
+ pid = task_pid($p);
+ name = task_execname($p);
+ open_ds = task_open_file_handles($p);
+ max_ds = task_rlimit_nofile($p);
+ if (failed_calls[name, pid] == "EMFILE") {
+ printf ("%s %s(%d) open: %d - max: %d Hit: %s\n",
+ ctime(gettimeofday_s()), name, pid, open_ds, max_ds,
+ failed_calls[name, pid]);
+ }
+}
+
+probe kernel.trace("sched_process_exit")
+{
+ pid = task_pid($p);
+ name = task_execname($p);
+ delete failed_calls[name, pid];
+}
+
+# This is exactly point where all the fun happens
+# This function returns only EMFILE errno.
+probe kernel.function("__alloc_fd@fs/file.c").return
+{
+ if (errno_str($return) == "EMFILE")
+ {
+ failed_calls[execname(), pid()] = errno_str($return);
+ }
+}