summaryrefslogtreecommitdiffstats
path: root/fs/notify/mark.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r--fs/notify/mark.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index f32ca924c44e..08ab7b252322 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -141,6 +141,30 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
}
}
+static struct inode *fsnotify_detach_from_object(struct fsnotify_mark *mark)
+{
+ struct fsnotify_mark_connector *conn;
+ struct inode *inode = NULL;
+ spinlock_t *lock;
+
+ conn = mark->connector;
+ if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ lock = &conn->inode->i_lock;
+ else
+ lock = &conn->mnt->mnt_root->d_lock;
+ spin_lock(lock);
+ hlist_del_init_rcu(&mark->obj_list);
+ if (hlist_empty(&conn->list)) {
+ if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ inode = conn->inode;
+ }
+ mark->connector = NULL;
+ spin_unlock(lock);
+ fsnotify_recalc_mask(conn);
+
+ return inode;
+}
+
/*
* Remove mark from inode / vfsmount list, group list, drop inode reference
* if we got one.
@@ -164,12 +188,8 @@ void fsnotify_detach_mark(struct fsnotify_mark *mark)
mark->flags &= ~FSNOTIFY_MARK_FLAG_ATTACHED;
- if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE)
- inode = fsnotify_destroy_inode_mark(mark);
- else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
- fsnotify_destroy_vfsmount_mark(mark);
- else
- BUG();
+ inode = fsnotify_detach_from_object(mark);
+
/*
* Note that we didn't update flags telling whether inode cares about
* what's happening with children. We update these flags from