mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 00:32:00 +00:00
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>
This commit is contained in:
parent
5a4e727d1a
commit
b782c5efe7
13
fs/mount.h
13
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);
|
||||
}
|
||||
|
@ -1155,16 +1155,25 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
|
||||
{
|
||||
struct rb_node **link = &ns->mounts.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
bool mnt_first_node = true, mnt_last_node = true;
|
||||
|
||||
WARN_ON(mnt_ns_attached(mnt));
|
||||
mnt->mnt_ns = ns;
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
if (mnt->mnt_id_unique < node_to_mount(parent)->mnt_id_unique)
|
||||
if (mnt->mnt_id_unique < node_to_mount(parent)->mnt_id_unique) {
|
||||
link = &parent->rb_left;
|
||||
else
|
||||
mnt_last_node = false;
|
||||
} else {
|
||||
link = &parent->rb_right;
|
||||
mnt_first_node = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mnt_last_node)
|
||||
ns->mnt_last_node = &mnt->mnt_node;
|
||||
if (mnt_first_node)
|
||||
ns->mnt_first_node = &mnt->mnt_node;
|
||||
rb_link_node(&mnt->mnt_node, parent, link);
|
||||
rb_insert_color(&mnt->mnt_node, &ns->mounts);
|
||||
}
|
||||
@ -5559,9 +5568,9 @@ static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
|
||||
|
||||
if (!last_mnt_id) {
|
||||
if (reverse)
|
||||
first = node_to_mount(rb_last(&ns->mounts));
|
||||
first = node_to_mount(ns->mnt_last_node);
|
||||
else
|
||||
first = node_to_mount(rb_first(&ns->mounts));
|
||||
first = node_to_mount(ns->mnt_first_node);
|
||||
} else {
|
||||
if (reverse)
|
||||
first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);
|
||||
|
Loading…
Reference in New Issue
Block a user