2012-12-18 04:05:12 +04:00
# include <linux/file.h>
# include <linux/fs.h>
# include <linux/fsnotify_backend.h>
# include <linux/idr.h>
# include <linux/init.h>
# include <linux/inotify.h>
# include <linux/fanotify.h>
# include <linux/kernel.h>
# include <linux/namei.h>
# include <linux/sched.h>
# include <linux/types.h>
# include <linux/seq_file.h>
# include <linux/proc_fs.h>
# include <linux/exportfs.h>
# include "inotify/inotify.h"
# include "../fs/mount.h"
# if defined(CONFIG_PROC_FS)
# if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
2014-09-30 03:08:25 +04:00
static void show_fdinfo ( struct seq_file * m , struct file * f ,
void ( * show ) ( struct seq_file * m ,
struct fsnotify_mark * mark ) )
2012-12-18 04:05:12 +04:00
{
struct fsnotify_group * group = f - > private_data ;
struct fsnotify_mark * mark ;
2012-12-21 08:11:52 +04:00
mutex_lock ( & group - > mark_mutex ) ;
2012-12-18 04:05:12 +04:00
list_for_each_entry ( mark , & group - > marks_list , g_list ) {
2014-09-30 03:08:25 +04:00
show ( m , mark ) ;
if ( seq_has_overflowed ( m ) )
2012-12-18 04:05:12 +04:00
break ;
}
2012-12-21 08:11:52 +04:00
mutex_unlock ( & group - > mark_mutex ) ;
2012-12-18 04:05:12 +04:00
}
# if defined(CONFIG_EXPORTFS)
2014-09-30 03:08:25 +04:00
static void show_mark_fhandle ( struct seq_file * m , struct inode * inode )
2012-12-18 04:05:12 +04:00
{
struct {
struct file_handle handle ;
2014-09-10 01:51:04 +04:00
u8 pad [ MAX_HANDLE_SZ ] ;
2012-12-18 04:05:12 +04:00
} f ;
int size , ret , i ;
f . handle . handle_bytes = sizeof ( f . pad ) ;
size = f . handle . handle_bytes > > 2 ;
ret = exportfs_encode_inode_fh ( inode , ( struct fid * ) f . handle . f_handle , & size , 0 ) ;
2014-09-10 01:51:06 +04:00
if ( ( ret = = FILEID_INVALID ) | | ( ret < 0 ) ) {
2012-12-18 04:05:12 +04:00
WARN_ONCE ( 1 , " Can't encode file handler for inotify: %d \n " , ret ) ;
2014-09-30 03:08:25 +04:00
return ;
2012-12-18 04:05:12 +04:00
}
f . handle . handle_type = ret ;
f . handle . handle_bytes = size * sizeof ( u32 ) ;
2014-09-30 03:08:25 +04:00
seq_printf ( m , " fhandle-bytes:%x fhandle-type:%x f_handle: " ,
f . handle . handle_bytes , f . handle . handle_type ) ;
2012-12-18 04:05:12 +04:00
for ( i = 0 ; i < f . handle . handle_bytes ; i + + )
2014-09-30 03:08:25 +04:00
seq_printf ( m , " %02x " , ( int ) f . handle . f_handle [ i ] ) ;
2012-12-18 04:05:12 +04:00
}
# else
2014-09-30 03:08:25 +04:00
static void show_mark_fhandle ( struct seq_file * m , struct inode * inode )
2012-12-18 04:05:12 +04:00
{
}
# endif
# ifdef CONFIG_INOTIFY_USER
2014-09-30 03:08:25 +04:00
static void inotify_fdinfo ( struct seq_file * m , struct fsnotify_mark * mark )
2012-12-18 04:05:12 +04:00
{
struct inotify_inode_mark * inode_mark ;
struct inode * inode ;
2017-03-14 16:29:35 +03:00
if ( ! ( mark - > connector - > flags & FSNOTIFY_OBJ_TYPE_INODE ) )
2014-09-30 03:08:25 +04:00
return ;
2012-12-18 04:05:12 +04:00
inode_mark = container_of ( mark , struct inotify_inode_mark , fsn_mark ) ;
2017-03-14 16:29:35 +03:00
inode = igrab ( mark - > connector - > inode ) ;
2012-12-18 04:05:12 +04:00
if ( inode ) {
2015-11-06 05:43:43 +03:00
/*
* IN_ALL_EVENTS represents all of the mask bits
* that we expose to userspace . There is at
* least one bit ( FS_EVENT_ON_CHILD ) which is
* used only internally to the kernel .
*/
u32 mask = mark - > mask & IN_ALL_EVENTS ;
2014-09-30 03:08:25 +04:00
seq_printf ( m , " inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:%x " ,
inode_mark - > wd , inode - > i_ino , inode - > i_sb - > s_dev ,
2015-11-06 05:43:43 +03:00
mask , mark - > ignored_mask ) ;
2014-09-30 03:08:25 +04:00
show_mark_fhandle ( m , inode ) ;
seq_putc ( m , ' \n ' ) ;
2012-12-18 04:05:12 +04:00
iput ( inode ) ;
}
}
2014-09-30 03:08:25 +04:00
void inotify_show_fdinfo ( struct seq_file * m , struct file * f )
2012-12-18 04:05:12 +04:00
{
2014-09-30 03:08:25 +04:00
show_fdinfo ( m , f , inotify_fdinfo ) ;
2012-12-18 04:05:12 +04:00
}
# endif /* CONFIG_INOTIFY_USER */
# ifdef CONFIG_FANOTIFY
2014-09-30 03:08:25 +04:00
static void fanotify_fdinfo ( struct seq_file * m , struct fsnotify_mark * mark )
2012-12-18 04:05:12 +04:00
{
2012-12-18 04:05:16 +04:00
unsigned int mflags = 0 ;
2012-12-18 04:05:12 +04:00
struct inode * inode ;
2012-12-18 04:05:16 +04:00
if ( mark - > flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY )
mflags | = FAN_MARK_IGNORED_SURV_MODIFY ;
2017-03-14 16:29:35 +03:00
if ( mark - > connector - > flags & FSNOTIFY_OBJ_TYPE_INODE ) {
inode = igrab ( mark - > connector - > inode ) ;
2012-12-18 04:05:12 +04:00
if ( ! inode )
2014-09-30 03:08:25 +04:00
return ;
seq_printf ( m , " fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x " ,
inode - > i_ino , inode - > i_sb - > s_dev ,
mflags , mark - > mask , mark - > ignored_mask ) ;
show_mark_fhandle ( m , inode ) ;
seq_putc ( m , ' \n ' ) ;
2012-12-18 04:05:12 +04:00
iput ( inode ) ;
2017-03-14 16:29:35 +03:00
} else if ( mark - > connector - > flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT ) {
struct mount * mnt = real_mount ( mark - > connector - > mnt ) ;
2012-12-18 04:05:12 +04:00
2014-09-30 03:08:25 +04:00
seq_printf ( m , " fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x \n " ,
mnt - > mnt_id , mflags , mark - > mask , mark - > ignored_mask ) ;
2012-12-18 04:05:12 +04:00
}
}
2014-09-30 03:08:25 +04:00
void fanotify_show_fdinfo ( struct seq_file * m , struct file * f )
2012-12-18 04:05:12 +04:00
{
struct fsnotify_group * group = f - > private_data ;
unsigned int flags = 0 ;
switch ( group - > priority ) {
case FS_PRIO_0 :
flags | = FAN_CLASS_NOTIF ;
break ;
case FS_PRIO_1 :
flags | = FAN_CLASS_CONTENT ;
break ;
case FS_PRIO_2 :
flags | = FAN_CLASS_PRE_CONTENT ;
break ;
}
if ( group - > max_events = = UINT_MAX )
flags | = FAN_UNLIMITED_QUEUE ;
if ( group - > fanotify_data . max_marks = = UINT_MAX )
flags | = FAN_UNLIMITED_MARKS ;
seq_printf ( m , " fanotify flags:%x event-flags:%x \n " ,
flags , group - > fanotify_data . f_flags ) ;
2014-09-30 03:08:25 +04:00
show_fdinfo ( m , f , fanotify_fdinfo ) ;
2012-12-18 04:05:12 +04:00
}
# endif /* CONFIG_FANOTIFY */
# endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */
# endif /* CONFIG_PROC_FS */