diff options
author | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:38 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:51 -0400 |
commit | 0c6532e4e3b0c8bd18dd0a5cc1894a1944997cc6 (patch) | |
tree | 05e9af0efc8018780a45e0c84d8264ceaf359729 /fs/notify/vfsmount_mark.c | |
parent | c1e5c954020e123d30b4abf4038ce501861bcf9f (diff) | |
download | linux-0c6532e4e3b0c8bd18dd0a5cc1894a1944997cc6.tar.bz2 |
fsnotify: place marks on object in order of group memory address
fsnotify_marks currently are placed on objects (inodes or vfsmounts) in
arbitrary order. This patch places them in order of the group memory address.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/vfsmount_mark.c')
-rw-r--r-- | fs/notify/vfsmount_mark.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c index ec580a25d293..c4b3f14d2530 100644 --- a/fs/notify/vfsmount_mark.c +++ b/fs/notify/vfsmount_mark.c @@ -141,34 +141,46 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, struct vfsmount *mnt, int allow_dups) { - struct fsnotify_mark *lmark = NULL; + struct fsnotify_mark *lmark; + struct hlist_node *node, *last = NULL; int ret = 0; mark->flags = FSNOTIFY_MARK_FLAG_VFSMOUNT; - /* - * LOCKING ORDER!!!! - * mark->lock - * group->mark_lock - * mnt->mnt_root->d_lock - */ assert_spin_locked(&mark->lock); assert_spin_locked(&group->mark_lock); spin_lock(&mnt->mnt_root->d_lock); - if (!allow_dups) - lmark = fsnotify_find_vfsmount_mark_locked(group, mnt); - if (!lmark) { - mark->m.mnt = mnt; + mark->m.mnt = mnt; + /* is mark the first mark? */ + if (hlist_empty(&mnt->mnt_fsnotify_marks)) { hlist_add_head(&mark->m.m_list, &mnt->mnt_fsnotify_marks); + goto out; + } + + /* should mark be in the middle of the current list? */ + hlist_for_each_entry(lmark, node, &mnt->mnt_fsnotify_marks, m.m_list) { + last = node; + + if ((lmark->group == group) && !allow_dups) { + ret = -EEXIST; + goto out; + } + + if (mark->group < lmark->group) + continue; - fsnotify_recalc_vfsmount_mask_locked(mnt); - } else { - ret = -EEXIST; + hlist_add_before(&mark->m.m_list, &lmark->m.m_list); + goto out; } + BUG_ON(last == NULL); + /* mark should be the last entry. last is the current last entry */ + hlist_add_after(last, &mark->m.m_list); +out: + fsnotify_recalc_vfsmount_mask_locked(mnt); spin_unlock(&mnt->mnt_root->d_lock); return ret; |