diff options
Diffstat (limited to 'fs/inotify.c')
| -rw-r--r-- | fs/inotify.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/inotify.c b/fs/inotify.c index 2c5b92152876..690e72595e6e 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
| @@ -168,20 +168,14 @@ static void set_dentry_child_flags(struct inode *inode, int watched) | |||
| 168 | struct dentry *child; | 168 | struct dentry *child; |
| 169 | 169 | ||
| 170 | list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { | 170 | list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { |
| 171 | if (!child->d_inode) { | 171 | if (!child->d_inode) |
| 172 | WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); | ||
| 173 | continue; | 172 | continue; |
| 174 | } | 173 | |
| 175 | spin_lock(&child->d_lock); | 174 | spin_lock(&child->d_lock); |
| 176 | if (watched) { | 175 | if (watched) |
| 177 | WARN_ON(child->d_flags & | ||
| 178 | DCACHE_INOTIFY_PARENT_WATCHED); | ||
| 179 | child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; | 176 | child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; |
| 180 | } else { | 177 | else |
| 181 | WARN_ON(!(child->d_flags & | 178 | child->d_flags &=~DCACHE_INOTIFY_PARENT_WATCHED; |
| 182 | DCACHE_INOTIFY_PARENT_WATCHED)); | ||
| 183 | child->d_flags&=~DCACHE_INOTIFY_PARENT_WATCHED; | ||
| 184 | } | ||
| 185 | spin_unlock(&child->d_lock); | 179 | spin_unlock(&child->d_lock); |
| 186 | } | 180 | } |
| 187 | } | 181 | } |
| @@ -253,7 +247,6 @@ void inotify_d_instantiate(struct dentry *entry, struct inode *inode) | |||
| 253 | if (!inode) | 247 | if (!inode) |
| 254 | return; | 248 | return; |
| 255 | 249 | ||
| 256 | WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); | ||
| 257 | spin_lock(&entry->d_lock); | 250 | spin_lock(&entry->d_lock); |
| 258 | parent = entry->d_parent; | 251 | parent = entry->d_parent; |
| 259 | if (parent->d_inode && inotify_inode_watched(parent->d_inode)) | 252 | if (parent->d_inode && inotify_inode_watched(parent->d_inode)) |
| @@ -627,6 +620,7 @@ s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch, | |||
| 627 | struct inode *inode, u32 mask) | 620 | struct inode *inode, u32 mask) |
| 628 | { | 621 | { |
| 629 | int ret = 0; | 622 | int ret = 0; |
| 623 | int newly_watched; | ||
| 630 | 624 | ||
| 631 | /* don't allow invalid bits: we don't want flags set */ | 625 | /* don't allow invalid bits: we don't want flags set */ |
| 632 | mask &= IN_ALL_EVENTS | IN_ONESHOT; | 626 | mask &= IN_ALL_EVENTS | IN_ONESHOT; |
| @@ -653,12 +647,18 @@ s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch, | |||
| 653 | */ | 647 | */ |
| 654 | watch->inode = igrab(inode); | 648 | watch->inode = igrab(inode); |
| 655 | 649 | ||
| 656 | if (!inotify_inode_watched(inode)) | ||
| 657 | set_dentry_child_flags(inode, 1); | ||
| 658 | |||
| 659 | /* Add the watch to the handle's and the inode's list */ | 650 | /* Add the watch to the handle's and the inode's list */ |
| 651 | newly_watched = !inotify_inode_watched(inode); | ||
| 660 | list_add(&watch->h_list, &ih->watches); | 652 | list_add(&watch->h_list, &ih->watches); |
| 661 | list_add(&watch->i_list, &inode->inotify_watches); | 653 | list_add(&watch->i_list, &inode->inotify_watches); |
| 654 | /* | ||
| 655 | * Set child flags _after_ adding the watch, so there is no race | ||
| 656 | * windows where newly instantiated children could miss their parent's | ||
| 657 | * watched flag. | ||
| 658 | */ | ||
| 659 | if (newly_watched) | ||
| 660 | set_dentry_child_flags(inode, 1); | ||
| 661 | |||
| 662 | out: | 662 | out: |
| 663 | mutex_unlock(&ih->mutex); | 663 | mutex_unlock(&ih->mutex); |
| 664 | mutex_unlock(&inode->inotify_mutex); | 664 | mutex_unlock(&inode->inotify_mutex); |
