Adds a readonly 'current_inotify_watches' entry to the user sysctl table. The handler for this entry is a custom function that ends up calling proc_dointvec. Said sysctl table already contains 'max_inotify_watches' and it gets mounted under /proc/sys/user/. Inotify watches are a finite resource, in a similar way to available file descriptors. The motivation for this patch is to be able to set up monitoring and alerting before an application starts failing because it runs out of inotify watches. Signed-off-by: Albert Vaca Cintora <albertvaka@xxxxxxxxx> Acked-by: Jan Kara <jack@xxxxxxx> Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@xxxxxxx> --- kernel/ucount.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/kernel/ucount.c b/kernel/ucount.c index 909c856e809f..05b0e76208d3 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -118,6 +118,26 @@ static void put_ucounts(struct ucounts *ucounts) kfree(ucounts); } +#ifdef CONFIG_INOTIFY_USER +int proc_read_inotify_watches(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ucounts *ucounts; + struct ctl_table fake_table; + int count = -1; + + ucounts = get_ucounts(current_user_ns(), current_euid()); + if (ucounts != NULL) { + count = atomic_read(&ucounts->ucount[UCOUNT_INOTIFY_WATCHES]); + put_ucounts(ucounts); + } + + fake_table.data = &count; + fake_table.maxlen = sizeof(count); + return proc_dointvec(&fake_table, write, buffer, lenp, ppos); +} +#endif + static int zero = 0; static int int_max = INT_MAX; #define UCOUNT_ENTRY(name) \ @@ -140,6 +160,12 @@ static struct ctl_table user_table[] = { #ifdef CONFIG_INOTIFY_USER UCOUNT_ENTRY("max_inotify_instances"), UCOUNT_ENTRY("max_inotify_watches"), + { + .procname = "current_inotify_watches", + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = proc_read_inotify_watches, + }, #endif { } }; -- 2.21.0