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: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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 {
|
|||||||
#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 {
|
|||||||
*/
|
*/
|
||||||
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
|
|||||||
/* 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);
|
||||||
|
Reference in New Issue
Block a user