fsnotify: use an explicit flag to indicate fsnotify_destroy_mark has been called
authorEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:38 +0000 (10:18 -0400)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:52 +0000 (10:18 -0400)
Currently fsnotify check is mark->group is NULL to decide if
fsnotify_destroy_mark() has already been called or not.  With the upcoming
rcu work it is a heck of a lot easier to use an explicit flag than worry
about group being set to NULL.

Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/inode_mark.c
fs/notify/mark.c
fs/notify/vfsmount_mark.c
include/linux/fsnotify_backend.h

index 455cb41c729b7b6f55ec8dbf8b90735cf6f93c14..37b460f302b785a0c01f5cc3e7b022d516e849eb 100644 (file)
@@ -187,7 +187,7 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
        struct hlist_node *node, *last = NULL;
        int ret = 0;
 
-       mark->flags = FSNOTIFY_MARK_FLAG_INODE;
+       mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
 
        assert_spin_locked(&mark->lock);
        assert_spin_locked(&group->mark_lock);
index 8f3b0e7a543dec3b547453ca9b8591bb4db2c174..69c5a166930c153f8b1844bce7e012e9dda3749b 100644 (file)
@@ -121,12 +121,14 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
        group = mark->group;
 
-       /* if !group something else already marked this to die */
-       if (!group) {
+       /* something else already called this function on this mark */
+       if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
                spin_unlock(&mark->lock);
                return;
        }
 
+       mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
+
        /* 1 from caller and 1 for being on i_list/g_list */
        BUG_ON(atomic_read(&mark->refcnt) < 2);
 
@@ -141,7 +143,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
                BUG();
 
        list_del_init(&mark->g_list);
-       mark->group = NULL;
 
        fsnotify_put_mark(mark); /* for i_list and g_list */
 
@@ -229,6 +230,8 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
        spin_lock(&mark->lock);
        spin_lock(&group->mark_lock);
 
+       mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
+
        mark->group = group;
        list_add(&mark->g_list, &group->marks_list);
        atomic_inc(&group->num_marks);
@@ -258,7 +261,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 
        return ret;
 err:
-       mark->group = NULL;
+       mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
        list_del_init(&mark->g_list);
        atomic_dec(&group->num_marks);
        fsnotify_put_mark(mark);
index b7ae64030021c9edd928fa0463c715e735d73aed..56772b578fbd546d62a199ad25f6b1dec859e660 100644 (file)
@@ -145,7 +145,7 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
        struct hlist_node *node, *last = NULL;
        int ret = 0;
 
-       mark->flags = FSNOTIFY_MARK_FLAG_VFSMOUNT;
+       mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 
        assert_spin_locked(&mark->lock);
        assert_spin_locked(&group->mark_lock);
index 3410d388163ebbd848b180a0f8dc9003d87fad09..8e24cdf72928e316177b67361e48577e9608ee75 100644 (file)
@@ -300,6 +300,7 @@ struct fsnotify_mark {
 #define FSNOTIFY_MARK_FLAG_VFSMOUNT            0x02
 #define FSNOTIFY_MARK_FLAG_OBJECT_PINNED       0x04
 #define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x08
+#define FSNOTIFY_MARK_FLAG_ALIVE               0x10
        unsigned int flags;             /* vfsmount or inode mark? */
        void (*free_mark)(struct fsnotify_mark *mark); /* called on final put+free */
 };