Commit d6f7b98b authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara

fsnotify: use type id to identify connector object type

An fsnotify_mark_connector is referencing a single type of object
(either inode or vfsmount). Instead of storing a type mask in
connector->flags, store a single type id in connector->type to
identify the type of object.

When a connector object is detached from the object, its type is set
to FSNOTIFY_OBJ_TYPE_DETACHED and this object is not going to be
reused.

The function fsnotify_clear_marks_by_group() is the only place where
type mask was used, so use type flags instead of type id to this
function.

This change is going to be more convenient when adding a new object
type (super block).
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 3acf4e39
...@@ -77,7 +77,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) ...@@ -77,7 +77,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
struct inotify_inode_mark *inode_mark; struct inotify_inode_mark *inode_mark;
struct inode *inode; struct inode *inode;
if (!(mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE)) if (mark->connector->type != FSNOTIFY_OBJ_TYPE_INODE)
return; return;
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
...@@ -116,7 +116,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) ...@@ -116,7 +116,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
mflags |= FAN_MARK_IGNORED_SURV_MODIFY; mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE) { if (mark->connector->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = igrab(mark->connector->inode); inode = igrab(mark->connector->inode);
if (!inode) if (!inode)
return; return;
...@@ -126,7 +126,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) ...@@ -126,7 +126,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
show_mark_fhandle(m, inode); show_mark_fhandle(m, inode);
seq_putc(m, '\n'); seq_putc(m, '\n');
iput(inode); iput(inode);
} else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) { } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
struct mount *mnt = real_mount(mark->connector->mnt); struct mount *mnt = real_mount(mark->connector->mnt);
seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
......
...@@ -67,7 +67,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group) ...@@ -67,7 +67,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
fsnotify_group_stop_queueing(group); fsnotify_group_stop_queueing(group);
/* Clear all marks for this group and queue them for destruction */ /* Clear all marks for this group and queue them for destruction */
fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES); fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES_MASK);
/* /*
* Some marks can still be pinned when waiting for response from * Some marks can still be pinned when waiting for response from
......
...@@ -119,9 +119,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) ...@@ -119,9 +119,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
new_mask |= mark->mask; new_mask |= mark->mask;
} }
if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
conn->inode->i_fsnotify_mask = new_mask; conn->inode->i_fsnotify_mask = new_mask;
else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask; real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
} }
...@@ -139,7 +139,7 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) ...@@ -139,7 +139,7 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
spin_lock(&conn->lock); spin_lock(&conn->lock);
__fsnotify_recalc_mask(conn); __fsnotify_recalc_mask(conn);
spin_unlock(&conn->lock); spin_unlock(&conn->lock);
if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
__fsnotify_update_child_dentry_flags(conn->inode); __fsnotify_update_child_dentry_flags(conn->inode);
} }
...@@ -166,18 +166,18 @@ static struct inode *fsnotify_detach_connector_from_object( ...@@ -166,18 +166,18 @@ static struct inode *fsnotify_detach_connector_from_object(
{ {
struct inode *inode = NULL; struct inode *inode = NULL;
if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) { if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = conn->inode; inode = conn->inode;
rcu_assign_pointer(inode->i_fsnotify_marks, NULL); rcu_assign_pointer(inode->i_fsnotify_marks, NULL);
inode->i_fsnotify_mask = 0; inode->i_fsnotify_mask = 0;
conn->inode = NULL; conn->inode = NULL;
conn->flags &= ~FSNOTIFY_OBJ_TYPE_INODE; conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
} else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) { } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks, rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks,
NULL); NULL);
real_mount(conn->mnt)->mnt_fsnotify_mask = 0; real_mount(conn->mnt)->mnt_fsnotify_mask = 0;
conn->mnt = NULL; conn->mnt = NULL;
conn->flags &= ~FSNOTIFY_OBJ_TYPE_VFSMOUNT; conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
} }
return inode; return inode;
...@@ -442,10 +442,10 @@ static int fsnotify_attach_connector_to_object( ...@@ -442,10 +442,10 @@ static int fsnotify_attach_connector_to_object(
spin_lock_init(&conn->lock); spin_lock_init(&conn->lock);
INIT_HLIST_HEAD(&conn->list); INIT_HLIST_HEAD(&conn->list);
if (inode) { if (inode) {
conn->flags = FSNOTIFY_OBJ_TYPE_INODE; conn->type = FSNOTIFY_OBJ_TYPE_INODE;
conn->inode = igrab(inode); conn->inode = igrab(inode);
} else { } else {
conn->flags = FSNOTIFY_OBJ_TYPE_VFSMOUNT; conn->type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
conn->mnt = mnt; conn->mnt = mnt;
} }
/* /*
...@@ -479,8 +479,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector( ...@@ -479,8 +479,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
if (!conn) if (!conn)
goto out; goto out;
spin_lock(&conn->lock); spin_lock(&conn->lock);
if (!(conn->flags & (FSNOTIFY_OBJ_TYPE_INODE | if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
FSNOTIFY_OBJ_TYPE_VFSMOUNT))) {
spin_unlock(&conn->lock); spin_unlock(&conn->lock);
srcu_read_unlock(&fsnotify_mark_srcu, idx); srcu_read_unlock(&fsnotify_mark_srcu, idx);
return NULL; return NULL;
...@@ -646,16 +645,16 @@ struct fsnotify_mark *fsnotify_find_mark( ...@@ -646,16 +645,16 @@ struct fsnotify_mark *fsnotify_find_mark(
return NULL; return NULL;
} }
/* Clear any marks in a group with given type */ /* Clear any marks in a group with given type mask */
void fsnotify_clear_marks_by_group(struct fsnotify_group *group, void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
unsigned int type) unsigned int type_mask)
{ {
struct fsnotify_mark *lmark, *mark; struct fsnotify_mark *lmark, *mark;
LIST_HEAD(to_free); LIST_HEAD(to_free);
struct list_head *head = &to_free; struct list_head *head = &to_free;
/* Skip selection step if we want to clear all marks. */ /* Skip selection step if we want to clear all marks. */
if (type == FSNOTIFY_OBJ_ALL_TYPES) { if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) {
head = &group->marks_list; head = &group->marks_list;
goto clear; goto clear;
} }
...@@ -670,7 +669,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group, ...@@ -670,7 +669,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
*/ */
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
if (mark->connector->flags & type) if ((1U << mark->connector->type) & type_mask)
list_move(&mark->g_list, &to_free); list_move(&mark->g_list, &to_free);
} }
mutex_unlock(&group->mark_mutex); mutex_unlock(&group->mark_mutex);
......
...@@ -201,6 +201,17 @@ struct fsnotify_group { ...@@ -201,6 +201,17 @@ struct fsnotify_group {
#define FSNOTIFY_EVENT_PATH 1 #define FSNOTIFY_EVENT_PATH 1
#define FSNOTIFY_EVENT_INODE 2 #define FSNOTIFY_EVENT_INODE 2
enum fsnotify_obj_type {
FSNOTIFY_OBJ_TYPE_INODE,
FSNOTIFY_OBJ_TYPE_VFSMOUNT,
FSNOTIFY_OBJ_TYPE_COUNT,
FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT
};
#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE)
#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT)
#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
/* /*
* Inode / vfsmount point to this structure which tracks all marks attached to * Inode / vfsmount point to this structure which tracks all marks attached to
* the inode / vfsmount. The reference to inode / vfsmount is held by this * the inode / vfsmount. The reference to inode / vfsmount is held by this
...@@ -209,11 +220,7 @@ struct fsnotify_group { ...@@ -209,11 +220,7 @@ struct fsnotify_group {
*/ */
struct fsnotify_mark_connector { struct fsnotify_mark_connector {
spinlock_t lock; spinlock_t lock;
#define FSNOTIFY_OBJ_TYPE_INODE 0x01 unsigned int type; /* Type of object [lock] */
#define FSNOTIFY_OBJ_TYPE_VFSMOUNT 0x02
#define FSNOTIFY_OBJ_ALL_TYPES (FSNOTIFY_OBJ_TYPE_INODE | \
FSNOTIFY_OBJ_TYPE_VFSMOUNT)
unsigned int flags; /* Type of object [lock] */
union { /* Object pointer [lock] */ union { /* Object pointer [lock] */
struct inode *inode; struct inode *inode;
struct vfsmount *mnt; struct vfsmount *mnt;
...@@ -369,12 +376,12 @@ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned ...@@ -369,12 +376,12 @@ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned
/* run all the marks in a group, and clear all of the vfsmount marks */ /* run all the marks in a group, and clear all of the vfsmount marks */
static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group)
{ {
fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT); fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL);
} }
/* run all the marks in a group, and clear all of the inode marks */ /* run all the marks in a group, and clear all of the inode marks */
static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group)
{ {
fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE); fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL);
} }
extern void fsnotify_get_mark(struct fsnotify_mark *mark); extern void fsnotify_get_mark(struct fsnotify_mark *mark);
extern void fsnotify_put_mark(struct fsnotify_mark *mark); extern void fsnotify_put_mark(struct fsnotify_mark *mark);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment