mirror of
https://github.com/torvalds/linux
synced 2024-10-15 07:47:34 +00:00
43b245a788
Create helpers to take and release the group mark_mutex lock. Define a flag FSNOTIFY_GROUP_NOFS in fsnotify_group that determines if the mark_mutex lock is fs reclaim safe or not. If not safe, the lock helpers take the lock and disable direct fs reclaim. In that case we annotate the mutex with a different lockdep class to express to lockdep that an allocation of mark of an fs reclaim safe group may take the group lock of another "NOFS" group to evict inodes. For now, converted only the callers in common code and no backend defines the NOFS flag. It is intended to be set by fanotify for evictable marks support. Link: https://lore.kernel.org/r/20220422120327.3459282-7-amir73il@gmail.com Suggested-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20220321112310.vpr7oxro2xkz5llh@quack3.lan/ Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
151 lines
4 KiB
C
151 lines
4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#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/exportfs.h>
|
|
|
|
#include "inotify/inotify.h"
|
|
#include "fdinfo.h"
|
|
#include "fsnotify.h"
|
|
|
|
#if defined(CONFIG_PROC_FS)
|
|
|
|
#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
|
|
|
|
static void show_fdinfo(struct seq_file *m, struct file *f,
|
|
void (*show)(struct seq_file *m,
|
|
struct fsnotify_mark *mark))
|
|
{
|
|
struct fsnotify_group *group = f->private_data;
|
|
struct fsnotify_mark *mark;
|
|
|
|
fsnotify_group_lock(group);
|
|
list_for_each_entry(mark, &group->marks_list, g_list) {
|
|
show(m, mark);
|
|
if (seq_has_overflowed(m))
|
|
break;
|
|
}
|
|
fsnotify_group_unlock(group);
|
|
}
|
|
|
|
#if defined(CONFIG_EXPORTFS)
|
|
static void show_mark_fhandle(struct seq_file *m, struct inode *inode)
|
|
{
|
|
struct {
|
|
struct file_handle handle;
|
|
u8 pad[MAX_HANDLE_SZ];
|
|
} 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, NULL);
|
|
if ((ret == FILEID_INVALID) || (ret < 0)) {
|
|
WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret);
|
|
return;
|
|
}
|
|
|
|
f.handle.handle_type = ret;
|
|
f.handle.handle_bytes = size * sizeof(u32);
|
|
|
|
seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:",
|
|
f.handle.handle_bytes, f.handle.handle_type);
|
|
|
|
for (i = 0; i < f.handle.handle_bytes; i++)
|
|
seq_printf(m, "%02x", (int)f.handle.f_handle[i]);
|
|
}
|
|
#else
|
|
static void show_mark_fhandle(struct seq_file *m, struct inode *inode)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_INOTIFY_USER
|
|
|
|
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
|
{
|
|
struct inotify_inode_mark *inode_mark;
|
|
struct inode *inode;
|
|
|
|
if (mark->connector->type != FSNOTIFY_OBJ_TYPE_INODE)
|
|
return;
|
|
|
|
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
|
|
inode = igrab(fsnotify_conn_inode(mark->connector));
|
|
if (inode) {
|
|
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
|
|
inode_mark->wd, inode->i_ino, inode->i_sb->s_dev,
|
|
inotify_mark_user_mask(mark));
|
|
show_mark_fhandle(m, inode);
|
|
seq_putc(m, '\n');
|
|
iput(inode);
|
|
}
|
|
}
|
|
|
|
void inotify_show_fdinfo(struct seq_file *m, struct file *f)
|
|
{
|
|
show_fdinfo(m, f, inotify_fdinfo);
|
|
}
|
|
|
|
#endif /* CONFIG_INOTIFY_USER */
|
|
|
|
#ifdef CONFIG_FANOTIFY
|
|
|
|
static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
|
{
|
|
unsigned int mflags = 0;
|
|
struct inode *inode;
|
|
|
|
if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
|
|
mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
|
|
|
|
if (mark->connector->type == FSNOTIFY_OBJ_TYPE_INODE) {
|
|
inode = igrab(fsnotify_conn_inode(mark->connector));
|
|
if (!inode)
|
|
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');
|
|
iput(inode);
|
|
} else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
|
|
struct mount *mnt = fsnotify_conn_mount(mark->connector);
|
|
|
|
seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
|
|
mnt->mnt_id, mflags, mark->mask, mark->ignored_mask);
|
|
} else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) {
|
|
struct super_block *sb = fsnotify_conn_sb(mark->connector);
|
|
|
|
seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n",
|
|
sb->s_dev, mflags, mark->mask, mark->ignored_mask);
|
|
}
|
|
}
|
|
|
|
void fanotify_show_fdinfo(struct seq_file *m, struct file *f)
|
|
{
|
|
struct fsnotify_group *group = f->private_data;
|
|
|
|
seq_printf(m, "fanotify flags:%x event-flags:%x\n",
|
|
group->fanotify_data.flags & FANOTIFY_INIT_FLAGS,
|
|
group->fanotify_data.f_flags);
|
|
|
|
show_fdinfo(m, f, fanotify_fdinfo);
|
|
}
|
|
|
|
#endif /* CONFIG_FANOTIFY */
|
|
|
|
#endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */
|
|
|
|
#endif /* CONFIG_PROC_FS */
|