mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-04-13 09:59:31 +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
c7bb042031
commit
2ce23285d7
2 changed files with 24 additions and 6 deletions
13
fs/mount.h
13
fs/mount.h
|
@ -8,7 +8,11 @@
|
||||||
struct mnt_namespace {
|
struct mnt_namespace {
|
||||||
struct ns_common ns;
|
struct ns_common ns;
|
||||||
struct mount * root;
|
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 user_namespace *user_ns;
|
||||||
struct ucounts *ucounts;
|
struct ucounts *ucounts;
|
||||||
u64 seq; /* Sequence number to prevent loops */
|
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)
|
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));
|
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);
|
RB_CLEAR_NODE(&mnt->mnt_node);
|
||||||
list_add_tail(&mnt->mnt_list, dt_list);
|
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 **link = &ns->mounts.rb_node;
|
||||||
struct rb_node *parent = NULL;
|
struct rb_node *parent = NULL;
|
||||||
|
bool mnt_first_node = true, mnt_last_node = true;
|
||||||
|
|
||||||
WARN_ON(mnt_ns_attached(mnt));
|
WARN_ON(mnt_ns_attached(mnt));
|
||||||
mnt->mnt_ns = ns;
|
mnt->mnt_ns = ns;
|
||||||
while (*link) {
|
while (*link) {
|
||||||
parent = *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;
|
link = &parent->rb_left;
|
||||||
else
|
mnt_last_node = false;
|
||||||
|
} else {
|
||||||
link = &parent->rb_right;
|
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_link_node(&mnt->mnt_node, parent, link);
|
||||||
rb_insert_color(&mnt->mnt_node, &ns->mounts);
|
rb_insert_color(&mnt->mnt_node, &ns->mounts);
|
||||||
}
|
}
|
||||||
|
@ -5563,9 +5572,9 @@ static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
|
||||||
|
|
||||||
if (!last_mnt_id) {
|
if (!last_mnt_id) {
|
||||||
if (reverse)
|
if (reverse)
|
||||||
first = node_to_mount(rb_last(&ns->mounts));
|
first = node_to_mount(ns->mnt_last_node);
|
||||||
else
|
else
|
||||||
first = node_to_mount(rb_first(&ns->mounts));
|
first = node_to_mount(ns->mnt_first_node);
|
||||||
} else {
|
} else {
|
||||||
if (reverse)
|
if (reverse)
|
||||||
first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);
|
first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);
|
||||||
|
|
Loading…
Add table
Reference in a new issue