[Devel] [PATCH RHEL7 COMMIT] proc/mounts: fix skipping mount after cursor

Vasily Averin vvs at virtuozzo.com
Fri Mar 26 17:46:29 MSK 2021


The commit is pushed to "branch-rh7-3.10.0-1160.21.1.vz7.174.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.21.1.vz7.174.2
------>
commit 0aee0dc817d1918dc478220deee7edd50e7d721f
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date:   Fri Mar 26 17:46:28 2021 +0300

    proc/mounts: fix skipping mount after cursor
    
    When reading mounts with:
    
      mount -t tmpfs $(printf 'T%.0s' {1..76}) /tmp/testmount
      tail -n1 /proc/self/mountinfo | wc
      #      1      10     128
      # len should be 128
      while read -r line; do echo $line; done < /proc/<pid>/mountinfo
    
    We can see that after TTT mount we stuck on it and show it infinitely.
    
    - Let's fix the case where we do m_start() and *pos == 0, in this case
    we need to reset cursor caches (last_pos and last_mntpos) as user asks
    us to start iterating from the beginning and we don't need to skip
    any mount based on these caches.
    
    - Let's set last_mntpos in m_stop and only in m_stop to actually make it
    cache the mount after cursor. There is no point to set it in m_next as
    cursor is inserted only in m_stop. Also let's reset last_mntpos to zero
    if cursor is removed for consistency.
    
    - Let's fix last_mntpos != mnt check in m_start, in case last_mntpos is
    unset we does not want to skip any mount.
    
    - Let's update last_pos in the end of m_start like in m_next. Where is a
    posibility that in seq_read we print one entry without calling m_next at
    all and go directly to m_stop and increment pos. If previously we had
    pos == last_poss, after first m_start pos would be == last_pos + 1, and
    after second m_start pos would be == last_pos + 2 and we would forget to
    skip mount and will be printing it forever infinitely.
    
    https://jira.sw.ru/browse/PSBM-127476
    
    Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
 fs/namespace.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 042ede7..a1c5afb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1457,6 +1457,8 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 	down_read(&namespace_sem);
 	if (!*pos) {
 		prev = &p->ns->list;
+		p->last_pos = 0;
+		p->last_mntpos = NULL;
 	} else {
 		prev = &p->cursor.mnt_list;
 
@@ -1509,10 +1511,10 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 	 * here and just remove following lines and p->last_pos field.
 	 */
 	if (mnt && (*pos == p->last_pos + 1) &&
-	    !(p->last_mntpos && (p->last_mntpos != mnt)))
+	    (p->last_mntpos == mnt))
 		mnt = mnt_list_next(p->ns, &mnt->mnt_list);
 
-	p->last_mntpos = mnt;
+	p->last_pos = *pos;
 
 	return mnt;
 }
@@ -1524,8 +1526,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 
 	++*pos;
 	p->last_pos = *pos;
-	p->last_mntpos = mnt_list_next(p->ns, &mnt->mnt_list);
-	return p->last_mntpos;
+	return mnt_list_next(p->ns, &mnt->mnt_list);
 }
 
 static void m_stop(struct seq_file *m, void *v)
@@ -1534,10 +1535,13 @@ static void m_stop(struct seq_file *m, void *v)
 	struct mount *mnt = v;
 
 	lock_ns_list(p->ns);
-	if (mnt)
+	if (mnt) {
 		list_move_tail(&p->cursor.mnt_list, &mnt->mnt_list);
-	else
+		p->last_mntpos = mnt;
+	} else {
 		list_del_init(&p->cursor.mnt_list);
+		p->last_mntpos = NULL;
+	}
 	unlock_ns_list(p->ns);
 	up_read(&namespace_sem);
 }


More information about the Devel mailing list