diff options
| author | Christian Brauner <brauner@kernel.org> | 2024-12-15 21:17:06 +0100 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2025-01-09 16:58:54 +0100 |
| commit | 2ce23285d704f6a8d90207ae8f115f5db93d3541 (patch) | |
| tree | 080356af151f07f9a31e568b77802cc6a87b5973 /fs/mount.h | |
| parent | c7bb042031b4890b1c5e733dd1ef6484565d174a (diff) | |
fs: cache first and last mount
Speed up listmount() by caching the first and last node making retrieval
of the first and last mount of each mount namespace O(1).
Link: https://lore.kernel.org/r/20241215-vfs-6-14-mount-work-v1-2-fd55922c4af8@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/mount.h')
| -rw-r--r-- | fs/mount.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/fs/mount.h b/fs/mount.h index e9f48e563c0f..ffb613cdfeee 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -8,7 +8,11 @@ struct mnt_namespace { struct ns_common ns; struct mount * root; - struct rb_root mounts; /* Protected by namespace_sem */ + struct { + struct rb_root mounts; /* Protected by namespace_sem */ + struct rb_node *mnt_last_node; /* last (rightmost) mount in the rbtree */ + struct rb_node *mnt_first_node; /* first (leftmost) mount in the rbtree */ + }; struct user_namespace *user_ns; struct ucounts *ucounts; u64 seq; /* Sequence number to prevent loops */ @@ -154,8 +158,13 @@ static inline bool mnt_ns_attached(const struct mount *mnt) static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list) { + struct mnt_namespace *ns = mnt->mnt_ns; WARN_ON(!mnt_ns_attached(mnt)); - rb_erase(&mnt->mnt_node, &mnt->mnt_ns->mounts); + if (ns->mnt_last_node == &mnt->mnt_node) + ns->mnt_last_node = rb_prev(&mnt->mnt_node); + if (ns->mnt_first_node == &mnt->mnt_node) + ns->mnt_first_node = rb_next(&mnt->mnt_node); + rb_erase(&mnt->mnt_node, &ns->mounts); RB_CLEAR_NODE(&mnt->mnt_node); list_add_tail(&mnt->mnt_list, dt_list); } |