Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 755b5bc6 authored by Jan Kara's avatar Jan Kara
Browse files

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: default avatarMiklos Szeredi <mszeredi@redhat.com>
Reviewed-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent e911d8af
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -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 */
+0 −25
Original line number Diff line number Diff line
@@ -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.
+43 −23
Original line number Diff line number Diff line
@@ -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();
	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 */
	spin_unlock(&mark->lock);

	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);
	ret = fsnotify_add_mark_list(mark, inode, mnt, allow_dups);
	if (ret)
		goto err;
	} else {
		BUG();
	}
	spin_unlock(&mark->lock);

	if (inode)
		__fsnotify_update_child_dentry_flags(inode);
		fsnotify_recalc_inode_mask(inode);
	else
		fsnotify_recalc_vfsmount_mask(mnt);

	return ret;
err:
+0 −24
Original line number Diff line number Diff line
@@ -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;
}