aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 20:12:05 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:17 -0400
commit40554c3dae83bd892b7fbfaa2ea9de739cbcf065 (patch)
tree7b9d4951734af9d819a900ff08f23c797a5c1b5c
parent9e1c74321d87a8b079f04d89e750b39a43365e1f (diff)
fsnotify: allow addition of duplicate fsnotify marks
This patch allows a task to add a second fsnotify mark to an inode for the same group. This mark will be added to the end of the inode's list and this will never be found by the stand fsnotify_find_mark() function. This is useful if a user wants to add a new mark before removing the old one. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/dnotify/dnotify.c2
-rw-r--r--fs/notify/inode_mark.c8
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--include/linux/fsnotify_backend.h2
-rw-r--r--kernel/audit_watch.c2
5 files changed, 9 insertions, 7 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 7e54e52964dd..85b97fca14de 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -362,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
362 dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry); 362 dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry);
363 spin_lock(&entry->lock); 363 spin_lock(&entry->lock);
364 } else { 364 } else {
365 fsnotify_add_mark(new_entry, dnotify_group, inode); 365 fsnotify_add_mark(new_entry, dnotify_group, inode, 0);
366 spin_lock(&new_entry->lock); 366 spin_lock(&new_entry->lock);
367 entry = new_entry; 367 entry = new_entry;
368 dnentry = new_dnentry; 368 dnentry = new_dnentry;
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index a13cf9e9233a..7d2962e5328e 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -312,9 +312,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
312 * event types should be delivered to which group and for which inodes. 312 * event types should be delivered to which group and for which inodes.
313 */ 313 */
314int fsnotify_add_mark(struct fsnotify_mark_entry *entry, 314int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
315 struct fsnotify_group *group, struct inode *inode) 315 struct fsnotify_group *group, struct inode *inode,
316 int allow_dups)
316{ 317{
317 struct fsnotify_mark_entry *lentry; 318 struct fsnotify_mark_entry *lentry = NULL;
318 int ret = 0; 319 int ret = 0;
319 320
320 inode = igrab(inode); 321 inode = igrab(inode);
@@ -331,7 +332,8 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
331 spin_lock(&group->mark_lock); 332 spin_lock(&group->mark_lock);
332 spin_lock(&inode->i_lock); 333 spin_lock(&inode->i_lock);
333 334
334 lentry = fsnotify_find_mark_entry(group, inode); 335 if (!allow_dups)
336 lentry = fsnotify_find_mark_entry(group, inode);
335 if (!lentry) { 337 if (!lentry) {
336 entry->group = group; 338 entry->group = group;
337 entry->inode = inode; 339 entry->inode = inode;
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 653c507b1bb3..f22a04005db2 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -651,7 +651,7 @@ static int inotify_new_watch(struct fsnotify_group *group,
651 goto out_err; 651 goto out_err;
652 652
653 /* we are on the idr, now get on the inode */ 653 /* we are on the idr, now get on the inode */
654 ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); 654 ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode, 0);
655 if (ret) { 655 if (ret) {
656 /* we failed to get on the inode, get off the idr */ 656 /* we failed to get on the inode, get off the idr */
657 inotify_remove_from_idr(group, tmp_ientry); 657 inotify_remove_from_idr(group, tmp_ientry);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 390516732956..1679f250d59e 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -345,7 +345,7 @@ extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_grou
345/* copy the values from old into new */ 345/* copy the values from old into new */
346extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old); 346extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old);
347/* attach the mark to both the group and the inode */ 347/* attach the mark to both the group and the inode */
348extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode); 348extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups);
349/* given a mark, flag it to be freed when all references are dropped */ 349/* given a mark, flag it to be freed when all references are dropped */
350extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry); 350extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry);
351/* run all the marks in a group, and flag them to be freed */ 351/* run all the marks in a group, and flag them to be freed */
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 75ab53987ece..c44de0c4fc47 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -161,7 +161,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp)
161 161
162 fsnotify_init_mark(&parent->mark, audit_watch_free_mark); 162 fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
163 parent->mark.mask = AUDIT_FS_WATCH; 163 parent->mark.mask = AUDIT_FS_WATCH;
164 ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode); 164 ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, 0);
165 if (ret < 0) { 165 if (ret < 0) {
166 audit_free_parent(parent); 166 audit_free_parent(parent);
167 return ERR_PTR(ret); 167 return ERR_PTR(ret);