forked from luck/tmp_suning_uos_patched
fsnotify: Remove indirection from mark list addition
Adding notification mark to object list has been currently done through fsnotify_add_{inode|vfsmount}_mark() helpers from fsnotify_add_mark_locked() which call fsnotify_add_mark_list(). Remove this unnecessary indirection to simplify the code. Pushing all the locking to fsnotify_add_mark_list() also allows us to allocate the connector structure with GFP_KERNEL mode. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
e911d8af87
commit
755b5bc681
|
@ -21,20 +21,6 @@ extern u32 fsnotify_recalc_mask(struct fsnotify_mark_connector *conn);
|
|||
extern int fsnotify_compare_groups(struct fsnotify_group *a,
|
||||
struct fsnotify_group *b);
|
||||
|
||||
/* Add mark to a proper place in mark list */
|
||||
extern int fsnotify_add_mark_list(struct fsnotify_mark_connector **connp,
|
||||
struct fsnotify_mark *mark,
|
||||
struct inode *inode, struct vfsmount *mnt,
|
||||
int allow_dups);
|
||||
/* add a mark to an inode */
|
||||
extern int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
|
||||
struct fsnotify_group *group, struct inode *inode,
|
||||
int allow_dups);
|
||||
/* add a mark to a vfsmount */
|
||||
extern int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
|
||||
struct fsnotify_group *group, struct vfsmount *mnt,
|
||||
int allow_dups);
|
||||
|
||||
/* vfsmount specific destruction of a mark */
|
||||
extern void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark);
|
||||
/* inode specific destruction of a mark */
|
||||
|
|
|
@ -92,31 +92,6 @@ struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group,
|
|||
return mark;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach an initialized mark to a given inode.
|
||||
* These marks may be used for the fsnotify backend to determine which
|
||||
* event types should be delivered to which group and for which inodes. These
|
||||
* marks are ordered according to priority, highest number first, and then by
|
||||
* the group's location in memory.
|
||||
*/
|
||||
int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
|
||||
struct fsnotify_group *group, struct inode *inode,
|
||||
int allow_dups)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&group->mark_mutex));
|
||||
assert_spin_locked(&mark->lock);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
ret = fsnotify_add_mark_list(&inode->i_fsnotify_marks, mark, inode,
|
||||
NULL, allow_dups);
|
||||
inode->i_fsnotify_mask = fsnotify_recalc_mask(inode->i_fsnotify_marks);
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
|
||||
* @sb: superblock being unmounted.
|
||||
|
|
|
@ -320,12 +320,13 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
|
|||
|
||||
static int fsnotify_attach_connector_to_object(
|
||||
struct fsnotify_mark_connector **connp,
|
||||
spinlock_t *lock,
|
||||
struct inode *inode,
|
||||
struct vfsmount *mnt)
|
||||
{
|
||||
struct fsnotify_mark_connector *conn;
|
||||
|
||||
conn = kmem_cache_alloc(fsnotify_mark_connector_cachep, GFP_ATOMIC);
|
||||
conn = kmem_cache_alloc(fsnotify_mark_connector_cachep, GFP_KERNEL);
|
||||
if (!conn)
|
||||
return -ENOMEM;
|
||||
INIT_HLIST_HEAD(&conn->list);
|
||||
|
@ -341,7 +342,12 @@ static int fsnotify_attach_connector_to_object(
|
|||
* lockless_dereference() in fsnotify().
|
||||
*/
|
||||
smp_wmb();
|
||||
*connp = conn;
|
||||
spin_lock(lock);
|
||||
if (!*connp)
|
||||
*connp = conn;
|
||||
else
|
||||
kmem_cache_free(fsnotify_mark_connector_cachep, conn);
|
||||
spin_unlock(lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -352,20 +358,35 @@ static int fsnotify_attach_connector_to_object(
|
|||
* to which group and for which inodes. These marks are ordered according to
|
||||
* priority, highest number first, and then by the group's location in memory.
|
||||
*/
|
||||
int fsnotify_add_mark_list(struct fsnotify_mark_connector **connp,
|
||||
struct fsnotify_mark *mark, struct inode *inode,
|
||||
struct vfsmount *mnt, int allow_dups)
|
||||
static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
|
||||
struct inode *inode, struct vfsmount *mnt,
|
||||
int allow_dups)
|
||||
{
|
||||
struct fsnotify_mark *lmark, *last = NULL;
|
||||
struct fsnotify_mark_connector *conn;
|
||||
struct fsnotify_mark_connector **connp;
|
||||
spinlock_t *lock;
|
||||
int cmp;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (WARN_ON(!inode && !mnt))
|
||||
return -EINVAL;
|
||||
if (inode) {
|
||||
connp = &inode->i_fsnotify_marks;
|
||||
lock = &inode->i_lock;
|
||||
} else {
|
||||
connp = &real_mount(mnt)->mnt_fsnotify_marks;
|
||||
lock = &mnt->mnt_root->d_lock;
|
||||
}
|
||||
|
||||
if (!*connp) {
|
||||
err = fsnotify_attach_connector_to_object(connp, inode, mnt);
|
||||
err = fsnotify_attach_connector_to_object(connp, lock,
|
||||
inode, mnt);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
spin_lock(&mark->lock);
|
||||
spin_lock(lock);
|
||||
conn = *connp;
|
||||
|
||||
/* is mark the first mark? */
|
||||
|
@ -380,8 +401,10 @@ int fsnotify_add_mark_list(struct fsnotify_mark_connector **connp,
|
|||
hlist_for_each_entry(lmark, &conn->list, obj_list) {
|
||||
last = lmark;
|
||||
|
||||
if ((lmark->group == mark->group) && !allow_dups)
|
||||
return -EEXIST;
|
||||
if ((lmark->group == mark->group) && !allow_dups) {
|
||||
err = -EEXIST;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
cmp = fsnotify_compare_groups(lmark->group, mark->group);
|
||||
if (cmp >= 0) {
|
||||
|
@ -395,7 +418,10 @@ int fsnotify_add_mark_list(struct fsnotify_mark_connector **connp,
|
|||
hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
|
||||
added:
|
||||
mark->connector = conn;
|
||||
return 0;
|
||||
out_err:
|
||||
spin_unlock(lock);
|
||||
spin_unlock(&mark->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -427,22 +453,16 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
|
|||
list_add(&mark->g_list, &group->marks_list);
|
||||
atomic_inc(&group->num_marks);
|
||||
fsnotify_get_mark(mark); /* for i_list and g_list */
|
||||
|
||||
if (inode) {
|
||||
ret = fsnotify_add_inode_mark(mark, group, inode, allow_dups);
|
||||
if (ret)
|
||||
goto err;
|
||||
} else if (mnt) {
|
||||
ret = fsnotify_add_vfsmount_mark(mark, group, mnt, allow_dups);
|
||||
if (ret)
|
||||
goto err;
|
||||
} else {
|
||||
BUG();
|
||||
}
|
||||
spin_unlock(&mark->lock);
|
||||
|
||||
ret = fsnotify_add_mark_list(mark, inode, mnt, allow_dups);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (inode)
|
||||
__fsnotify_update_child_dentry_flags(inode);
|
||||
fsnotify_recalc_inode_mask(inode);
|
||||
else
|
||||
fsnotify_recalc_vfsmount_mask(mnt);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
|
|
|
@ -80,27 +80,3 @@ struct fsnotify_mark *fsnotify_find_vfsmount_mark(struct fsnotify_group *group,
|
|||
|
||||
return mark;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach an initialized mark to a given group and vfsmount.
|
||||
* These marks may be used for the fsnotify backend to determine which
|
||||
* event types should be delivered to which groups.
|
||||
*/
|
||||
int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
|
||||
struct fsnotify_group *group, struct vfsmount *mnt,
|
||||
int allow_dups)
|
||||
{
|
||||
struct mount *m = real_mount(mnt);
|
||||
int ret;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&group->mark_mutex));
|
||||
assert_spin_locked(&mark->lock);
|
||||
|
||||
spin_lock(&mnt->mnt_root->d_lock);
|
||||
ret = fsnotify_add_mark_list(&m->mnt_fsnotify_marks, mark, NULL, mnt,
|
||||
allow_dups);
|
||||
m->mnt_fsnotify_mask = fsnotify_recalc_mask(m->mnt_fsnotify_marks);
|
||||
spin_unlock(&mnt->mnt_root->d_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user