Skip to content

Commit 2ce2328

Browse files
committed
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/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent c7bb042 commit 2ce2328

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

fs/mount.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
struct mnt_namespace {
99
struct ns_common ns;
1010
struct mount * root;
11-
struct rb_root mounts; /* Protected by namespace_sem */
11+
struct {
12+
struct rb_root mounts; /* Protected by namespace_sem */
13+
struct rb_node *mnt_last_node; /* last (rightmost) mount in the rbtree */
14+
struct rb_node *mnt_first_node; /* first (leftmost) mount in the rbtree */
15+
};
1216
struct user_namespace *user_ns;
1317
struct ucounts *ucounts;
1418
u64 seq; /* Sequence number to prevent loops */
@@ -154,8 +158,13 @@ static inline bool mnt_ns_attached(const struct mount *mnt)
154158

155159
static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
156160
{
161+
struct mnt_namespace *ns = mnt->mnt_ns;
157162
WARN_ON(!mnt_ns_attached(mnt));
158-
rb_erase(&mnt->mnt_node, &mnt->mnt_ns->mounts);
163+
if (ns->mnt_last_node == &mnt->mnt_node)
164+
ns->mnt_last_node = rb_prev(&mnt->mnt_node);
165+
if (ns->mnt_first_node == &mnt->mnt_node)
166+
ns->mnt_first_node = rb_next(&mnt->mnt_node);
167+
rb_erase(&mnt->mnt_node, &ns->mounts);
159168
RB_CLEAR_NODE(&mnt->mnt_node);
160169
list_add_tail(&mnt->mnt_list, dt_list);
161170
}

fs/namespace.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,16 +1155,25 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
11551155
{
11561156
struct rb_node **link = &ns->mounts.rb_node;
11571157
struct rb_node *parent = NULL;
1158+
bool mnt_first_node = true, mnt_last_node = true;
11581159

11591160
WARN_ON(mnt_ns_attached(mnt));
11601161
mnt->mnt_ns = ns;
11611162
while (*link) {
11621163
parent = *link;
1163-
if (mnt->mnt_id_unique < node_to_mount(parent)->mnt_id_unique)
1164+
if (mnt->mnt_id_unique < node_to_mount(parent)->mnt_id_unique) {
11641165
link = &parent->rb_left;
1165-
else
1166+
mnt_last_node = false;
1167+
} else {
11661168
link = &parent->rb_right;
1169+
mnt_first_node = false;
1170+
}
11671171
}
1172+
1173+
if (mnt_last_node)
1174+
ns->mnt_last_node = &mnt->mnt_node;
1175+
if (mnt_first_node)
1176+
ns->mnt_first_node = &mnt->mnt_node;
11681177
rb_link_node(&mnt->mnt_node, parent, link);
11691178
rb_insert_color(&mnt->mnt_node, &ns->mounts);
11701179
}
@@ -5563,9 +5572,9 @@ static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
55635572

55645573
if (!last_mnt_id) {
55655574
if (reverse)
5566-
first = node_to_mount(rb_last(&ns->mounts));
5575+
first = node_to_mount(ns->mnt_last_node);
55675576
else
5568-
first = node_to_mount(rb_first(&ns->mounts));
5577+
first = node_to_mount(ns->mnt_first_node);
55695578
} else {
55705579
if (reverse)
55715580
first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);

0 commit comments

Comments
 (0)