fsnotify keeps a count of watched objects per superblock so that the event hooks can be skipped on a superblock nobody watches. It computes the superblock from the object object it watches via fsnotify_object_sb(). This currently works because an object's superblock doesn't change while a connector is attached to it. This changes form some of them. So record the superblock in the connector when it is created and use that for the accounting. No functional changes. Signed-off-by: Christian Brauner (Amutable) --- fs/notify/fsnotify.h | 3 ++- fs/notify/mark.c | 7 +++++-- include/linux/fsnotify_backend.h | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 58c7bb25e571..0be351275dad 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h @@ -54,10 +54,11 @@ static inline struct super_block *fsnotify_object_sb(void *obj, } } +/* The sb the connector is accounted on; NULL once it has been detached */ static inline struct super_block *fsnotify_connector_sb( struct fsnotify_mark_connector *conn) { - return fsnotify_object_sb(conn->obj, conn->type); + return conn->sb; } static inline fsnotify_connp_t *fsnotify_sb_marks(struct super_block *sb) diff --git a/fs/notify/mark.c b/fs/notify/mark.c index b2640d836a71..1b6095fcf039 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -425,6 +425,7 @@ static void *fsnotify_detach_connector_from_object( conn->type = FSNOTIFY_OBJ_TYPE_DETACHED; if (sb) fsnotify_update_sb_watchers(sb, conn); + conn->sb = NULL; return inode; } @@ -791,6 +792,8 @@ static void fsnotify_init_connector(struct fsnotify_mark_connector *conn, conn->prio = 0; conn->type = obj_type; conn->obj = obj; + /* the object may move to another sb, the accounting doesn't */ + conn->sb = fsnotify_object_sb(obj, obj_type); } static struct fsnotify_mark_connector * @@ -953,8 +956,8 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj, /* mark should be the last entry. last is the current last entry */ hlist_add_behind_rcu(&mark->obj_list, &last->obj_list); added: - if (sb) - fsnotify_update_sb_watchers(sb, conn); + if (conn->sb) + fsnotify_update_sb_watchers(conn->sb, conn); /* * Since connector is attached to object using cmpxchg() we are * guaranteed that connector initialization is fully visible by anyone diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 618eed4d6d72..3a9ab9e0104b 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -573,6 +573,8 @@ struct fsnotify_mark_connector { /* Used listing heads to free after srcu period expires */ struct fsnotify_mark_connector *destroy_next; }; + /* sb whose watched_objects account for this connector [lock] */ + struct super_block *sb; struct hlist_head list; /* List of marks */ }; -- 2.53.0