1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2be77196bSCyrill Gorcunov #include <linux/file.h> 3be77196bSCyrill Gorcunov #include <linux/fs.h> 4be77196bSCyrill Gorcunov #include <linux/fsnotify_backend.h> 5be77196bSCyrill Gorcunov #include <linux/idr.h> 6be77196bSCyrill Gorcunov #include <linux/init.h> 7be77196bSCyrill Gorcunov #include <linux/inotify.h> 8be77196bSCyrill Gorcunov #include <linux/fanotify.h> 9be77196bSCyrill Gorcunov #include <linux/kernel.h> 10be77196bSCyrill Gorcunov #include <linux/namei.h> 11be77196bSCyrill Gorcunov #include <linux/sched.h> 12be77196bSCyrill Gorcunov #include <linux/types.h> 13be77196bSCyrill Gorcunov #include <linux/seq_file.h> 14be77196bSCyrill Gorcunov #include <linux/proc_fs.h> 15be77196bSCyrill Gorcunov #include <linux/exportfs.h> 16be77196bSCyrill Gorcunov 17be77196bSCyrill Gorcunov #include "inotify/inotify.h" 18be77196bSCyrill Gorcunov #include "../fs/mount.h" 19be77196bSCyrill Gorcunov 20be77196bSCyrill Gorcunov #if defined(CONFIG_PROC_FS) 21be77196bSCyrill Gorcunov 22be77196bSCyrill Gorcunov #if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY) 23be77196bSCyrill Gorcunov 24a3816ab0SJoe Perches static void show_fdinfo(struct seq_file *m, struct file *f, 25a3816ab0SJoe Perches void (*show)(struct seq_file *m, 26a3816ab0SJoe Perches struct fsnotify_mark *mark)) 27be77196bSCyrill Gorcunov { 28be77196bSCyrill Gorcunov struct fsnotify_group *group = f->private_data; 29be77196bSCyrill Gorcunov struct fsnotify_mark *mark; 30be77196bSCyrill Gorcunov 3196680d2bSLinus Torvalds mutex_lock(&group->mark_mutex); 32be77196bSCyrill Gorcunov list_for_each_entry(mark, &group->marks_list, g_list) { 33a3816ab0SJoe Perches show(m, mark); 34a3816ab0SJoe Perches if (seq_has_overflowed(m)) 35be77196bSCyrill Gorcunov break; 36be77196bSCyrill Gorcunov } 3796680d2bSLinus Torvalds mutex_unlock(&group->mark_mutex); 38be77196bSCyrill Gorcunov } 39be77196bSCyrill Gorcunov 40be77196bSCyrill Gorcunov #if defined(CONFIG_EXPORTFS) 41a3816ab0SJoe Perches static void show_mark_fhandle(struct seq_file *m, struct inode *inode) 42be77196bSCyrill Gorcunov { 43be77196bSCyrill Gorcunov struct { 44be77196bSCyrill Gorcunov struct file_handle handle; 451fc98d11SAndrey Vagin u8 pad[MAX_HANDLE_SZ]; 46be77196bSCyrill Gorcunov } f; 47be77196bSCyrill Gorcunov int size, ret, i; 48be77196bSCyrill Gorcunov 49be77196bSCyrill Gorcunov f.handle.handle_bytes = sizeof(f.pad); 50be77196bSCyrill Gorcunov size = f.handle.handle_bytes >> 2; 51be77196bSCyrill Gorcunov 52be77196bSCyrill Gorcunov ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); 537e882481SAndrey Vagin if ((ret == FILEID_INVALID) || (ret < 0)) { 54be77196bSCyrill Gorcunov WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); 55a3816ab0SJoe Perches return; 56be77196bSCyrill Gorcunov } 57be77196bSCyrill Gorcunov 58be77196bSCyrill Gorcunov f.handle.handle_type = ret; 59be77196bSCyrill Gorcunov f.handle.handle_bytes = size * sizeof(u32); 60be77196bSCyrill Gorcunov 61a3816ab0SJoe Perches seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:", 62be77196bSCyrill Gorcunov f.handle.handle_bytes, f.handle.handle_type); 63be77196bSCyrill Gorcunov 64be77196bSCyrill Gorcunov for (i = 0; i < f.handle.handle_bytes; i++) 65a3816ab0SJoe Perches seq_printf(m, "%02x", (int)f.handle.f_handle[i]); 66be77196bSCyrill Gorcunov } 67be77196bSCyrill Gorcunov #else 68a3816ab0SJoe Perches static void show_mark_fhandle(struct seq_file *m, struct inode *inode) 69be77196bSCyrill Gorcunov { 70be77196bSCyrill Gorcunov } 71be77196bSCyrill Gorcunov #endif 72be77196bSCyrill Gorcunov 73be77196bSCyrill Gorcunov #ifdef CONFIG_INOTIFY_USER 74be77196bSCyrill Gorcunov 75a3816ab0SJoe Perches static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) 76be77196bSCyrill Gorcunov { 77be77196bSCyrill Gorcunov struct inotify_inode_mark *inode_mark; 78be77196bSCyrill Gorcunov struct inode *inode; 79be77196bSCyrill Gorcunov 8086ffe245SJan Kara if (!(mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE)) 81a3816ab0SJoe Perches return; 82be77196bSCyrill Gorcunov 83be77196bSCyrill Gorcunov inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); 8486ffe245SJan Kara inode = igrab(mark->connector->inode); 85be77196bSCyrill Gorcunov if (inode) { 8669335996SDave Hansen /* 8769335996SDave Hansen * IN_ALL_EVENTS represents all of the mask bits 8869335996SDave Hansen * that we expose to userspace. There is at 8969335996SDave Hansen * least one bit (FS_EVENT_ON_CHILD) which is 9069335996SDave Hansen * used only internally to the kernel. 9169335996SDave Hansen */ 9269335996SDave Hansen u32 mask = mark->mask & IN_ALL_EVENTS; 93a3816ab0SJoe Perches seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:%x ", 94a3816ab0SJoe Perches inode_mark->wd, inode->i_ino, inode->i_sb->s_dev, 9569335996SDave Hansen mask, mark->ignored_mask); 96a3816ab0SJoe Perches show_mark_fhandle(m, inode); 97a3816ab0SJoe Perches seq_putc(m, '\n'); 98be77196bSCyrill Gorcunov iput(inode); 99be77196bSCyrill Gorcunov } 100be77196bSCyrill Gorcunov } 101be77196bSCyrill Gorcunov 102a3816ab0SJoe Perches void inotify_show_fdinfo(struct seq_file *m, struct file *f) 103be77196bSCyrill Gorcunov { 104a3816ab0SJoe Perches show_fdinfo(m, f, inotify_fdinfo); 105be77196bSCyrill Gorcunov } 106be77196bSCyrill Gorcunov 107be77196bSCyrill Gorcunov #endif /* CONFIG_INOTIFY_USER */ 108be77196bSCyrill Gorcunov 109be77196bSCyrill Gorcunov #ifdef CONFIG_FANOTIFY 110be77196bSCyrill Gorcunov 111a3816ab0SJoe Perches static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) 112be77196bSCyrill Gorcunov { 113e6dbcafbSCyrill Gorcunov unsigned int mflags = 0; 114be77196bSCyrill Gorcunov struct inode *inode; 115be77196bSCyrill Gorcunov 116e6dbcafbSCyrill Gorcunov if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) 117e6dbcafbSCyrill Gorcunov mflags |= FAN_MARK_IGNORED_SURV_MODIFY; 118e6dbcafbSCyrill Gorcunov 11986ffe245SJan Kara if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE) { 12086ffe245SJan Kara inode = igrab(mark->connector->inode); 121be77196bSCyrill Gorcunov if (!inode) 122a3816ab0SJoe Perches return; 123a3816ab0SJoe Perches seq_printf(m, "fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x ", 124be77196bSCyrill Gorcunov inode->i_ino, inode->i_sb->s_dev, 125e6dbcafbSCyrill Gorcunov mflags, mark->mask, mark->ignored_mask); 126a3816ab0SJoe Perches show_mark_fhandle(m, inode); 127a3816ab0SJoe Perches seq_putc(m, '\n'); 128be77196bSCyrill Gorcunov iput(inode); 12986ffe245SJan Kara } else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) { 13086ffe245SJan Kara struct mount *mnt = real_mount(mark->connector->mnt); 131be77196bSCyrill Gorcunov 132a3816ab0SJoe Perches seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", 133a3816ab0SJoe Perches mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); 134be77196bSCyrill Gorcunov } 135be77196bSCyrill Gorcunov } 136be77196bSCyrill Gorcunov 137a3816ab0SJoe Perches void fanotify_show_fdinfo(struct seq_file *m, struct file *f) 138be77196bSCyrill Gorcunov { 139be77196bSCyrill Gorcunov struct fsnotify_group *group = f->private_data; 140be77196bSCyrill Gorcunov unsigned int flags = 0; 141be77196bSCyrill Gorcunov 142be77196bSCyrill Gorcunov switch (group->priority) { 143be77196bSCyrill Gorcunov case FS_PRIO_0: 144be77196bSCyrill Gorcunov flags |= FAN_CLASS_NOTIF; 145be77196bSCyrill Gorcunov break; 146be77196bSCyrill Gorcunov case FS_PRIO_1: 147be77196bSCyrill Gorcunov flags |= FAN_CLASS_CONTENT; 148be77196bSCyrill Gorcunov break; 149be77196bSCyrill Gorcunov case FS_PRIO_2: 150be77196bSCyrill Gorcunov flags |= FAN_CLASS_PRE_CONTENT; 151be77196bSCyrill Gorcunov break; 152be77196bSCyrill Gorcunov } 153be77196bSCyrill Gorcunov 154be77196bSCyrill Gorcunov if (group->max_events == UINT_MAX) 155be77196bSCyrill Gorcunov flags |= FAN_UNLIMITED_QUEUE; 156be77196bSCyrill Gorcunov 157be77196bSCyrill Gorcunov if (group->fanotify_data.max_marks == UINT_MAX) 158be77196bSCyrill Gorcunov flags |= FAN_UNLIMITED_MARKS; 159be77196bSCyrill Gorcunov 160be77196bSCyrill Gorcunov seq_printf(m, "fanotify flags:%x event-flags:%x\n", 161be77196bSCyrill Gorcunov flags, group->fanotify_data.f_flags); 162be77196bSCyrill Gorcunov 163a3816ab0SJoe Perches show_fdinfo(m, f, fanotify_fdinfo); 164be77196bSCyrill Gorcunov } 165be77196bSCyrill Gorcunov 166be77196bSCyrill Gorcunov #endif /* CONFIG_FANOTIFY */ 167be77196bSCyrill Gorcunov 168be77196bSCyrill Gorcunov #endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */ 169be77196bSCyrill Gorcunov 170be77196bSCyrill Gorcunov #endif /* CONFIG_PROC_FS */ 171