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 | |
| parent | c1e5c954020e123d30b4abf4038ce501861bcf9f (diff) | |
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')
| -rw-r--r-- | fs/notify/inode_mark.c | 40 | ||||
| -rw-r--r-- | fs/notify/vfsmount_mark.c | 40 |
2 files changed, 55 insertions, 25 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 0c0a48b1659f..83ce6db34039 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
| @@ -174,15 +174,17 @@ void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *mark, | |||
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | /* | 176 | /* |
| 177 | * Attach an initialized mark to a given group and inode. | 177 | * Attach an initialized mark to a given inode. |
| 178 | * These marks may be used for the fsnotify backend to determine which | 178 | * These marks may be used for the fsnotify backend to determine which |
| 179 | * event types should be delivered to which group and for which inodes. | 179 | * event types should be delivered to which group and for which inodes. These |
| 180 | * marks are ordered according to the group's location in memory. | ||
| 180 | */ | 181 | */ |
| 181 | int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | 182 | int fsnotify_add_inode_mark(struct fsnotify_mark *mark, |
| 182 | struct fsnotify_group *group, struct inode *inode, | 183 | struct fsnotify_group *group, struct inode *inode, |
| 183 | int allow_dups) | 184 | int allow_dups) |
| 184 | { | 185 | { |
| 185 | struct fsnotify_mark *lmark = NULL; | 186 | struct fsnotify_mark *lmark; |
| 187 | struct hlist_node *node, *last = NULL; | ||
| 186 | int ret = 0; | 188 | int ret = 0; |
| 187 | 189 | ||
| 188 | mark->flags = FSNOTIFY_MARK_FLAG_INODE; | 190 | mark->flags = FSNOTIFY_MARK_FLAG_INODE; |
| @@ -192,21 +194,37 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
| 192 | 194 | ||
| 193 | spin_lock(&inode->i_lock); | 195 | spin_lock(&inode->i_lock); |
| 194 | 196 | ||
| 195 | if (!allow_dups) | 197 | mark->i.inode = inode; |
| 196 | lmark = fsnotify_find_inode_mark_locked(group, inode); | ||
| 197 | if (!lmark) { | ||
| 198 | mark->i.inode = inode; | ||
| 199 | 198 | ||
| 199 | /* is mark the first mark? */ | ||
| 200 | if (hlist_empty(&inode->i_fsnotify_marks)) { | ||
| 200 | hlist_add_head(&mark->i.i_list, &inode->i_fsnotify_marks); | 201 | hlist_add_head(&mark->i.i_list, &inode->i_fsnotify_marks); |
| 202 | goto out; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* should mark be in the middle of the current list? */ | ||
| 206 | hlist_for_each_entry(lmark, node, &inode->i_fsnotify_marks, i.i_list) { | ||
| 207 | last = node; | ||
| 208 | |||
| 209 | if ((lmark->group == group) && !allow_dups) { | ||
| 210 | ret = -EEXIST; | ||
| 211 | goto out; | ||
| 212 | } | ||
| 201 | 213 | ||
| 202 | fsnotify_recalc_inode_mask_locked(inode); | 214 | if (mark->group < lmark->group) |
| 215 | continue; | ||
| 216 | |||
| 217 | hlist_add_before(&mark->i.i_list, &lmark->i.i_list); | ||
| 218 | goto out; | ||
| 203 | } | 219 | } |
| 204 | 220 | ||
| 221 | BUG_ON(last == NULL); | ||
| 222 | /* mark should be the last entry. last is the current last entry */ | ||
| 223 | hlist_add_after(last, &mark->i.i_list); | ||
| 224 | out: | ||
| 225 | fsnotify_recalc_inode_mask_locked(inode); | ||
| 205 | spin_unlock(&inode->i_lock); | 226 | spin_unlock(&inode->i_lock); |
| 206 | 227 | ||
| 207 | if (lmark) | ||
| 208 | ret = -EEXIST; | ||
| 209 | |||
| 210 | return ret; | 228 | return ret; |
| 211 | } | 229 | } |
| 212 | 230 | ||
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, | |||
| 141 | struct fsnotify_group *group, struct vfsmount *mnt, | 141 | struct fsnotify_group *group, struct vfsmount *mnt, |
| 142 | int allow_dups) | 142 | int allow_dups) |
| 143 | { | 143 | { |
| 144 | struct fsnotify_mark *lmark = NULL; | 144 | struct fsnotify_mark *lmark; |
| 145 | struct hlist_node *node, *last = NULL; | ||
| 145 | int ret = 0; | 146 | int ret = 0; |
| 146 | 147 | ||
| 147 | mark->flags = FSNOTIFY_MARK_FLAG_VFSMOUNT; | 148 | mark->flags = FSNOTIFY_MARK_FLAG_VFSMOUNT; |
| 148 | 149 | ||
| 149 | /* | ||
| 150 | * LOCKING ORDER!!!! | ||
| 151 | * mark->lock | ||
| 152 | * group->mark_lock | ||
| 153 | * mnt->mnt_root->d_lock | ||
| 154 | */ | ||
| 155 | assert_spin_locked(&mark->lock); | 150 | assert_spin_locked(&mark->lock); |
| 156 | assert_spin_locked(&group->mark_lock); | 151 | assert_spin_locked(&group->mark_lock); |
| 157 | 152 | ||
| 158 | spin_lock(&mnt->mnt_root->d_lock); | 153 | spin_lock(&mnt->mnt_root->d_lock); |
| 159 | 154 | ||
| 160 | if (!allow_dups) | 155 | mark->m.mnt = mnt; |
| 161 | lmark = fsnotify_find_vfsmount_mark_locked(group, mnt); | ||
| 162 | if (!lmark) { | ||
| 163 | mark->m.mnt = mnt; | ||
| 164 | 156 | ||
| 157 | /* is mark the first mark? */ | ||
| 158 | if (hlist_empty(&mnt->mnt_fsnotify_marks)) { | ||
| 165 | hlist_add_head(&mark->m.m_list, &mnt->mnt_fsnotify_marks); | 159 | hlist_add_head(&mark->m.m_list, &mnt->mnt_fsnotify_marks); |
| 160 | goto out; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* should mark be in the middle of the current list? */ | ||
| 164 | hlist_for_each_entry(lmark, node, &mnt->mnt_fsnotify_marks, m.m_list) { | ||
| 165 | last = node; | ||
| 166 | |||
| 167 | if ((lmark->group == group) && !allow_dups) { | ||
| 168 | ret = -EEXIST; | ||
| 169 | goto out; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (mark->group < lmark->group) | ||
| 173 | continue; | ||
| 166 | 174 | ||
| 167 | fsnotify_recalc_vfsmount_mask_locked(mnt); | 175 | hlist_add_before(&mark->m.m_list, &lmark->m.m_list); |
| 168 | } else { | 176 | goto out; |
| 169 | ret = -EEXIST; | ||
| 170 | } | 177 | } |
| 171 | 178 | ||
| 179 | BUG_ON(last == NULL); | ||
| 180 | /* mark should be the last entry. last is the current last entry */ | ||
| 181 | hlist_add_after(last, &mark->m.m_list); | ||
| 182 | out: | ||
| 183 | fsnotify_recalc_vfsmount_mask_locked(mnt); | ||
| 172 | spin_unlock(&mnt->mnt_root->d_lock); | 184 | spin_unlock(&mnt->mnt_root->d_lock); |
| 173 | 185 | ||
| 174 | return ret; | 186 | return ret; |
