From 1efb88fbf554f3977a1a8aa1c79bc70cc1b66953 Mon Sep 17 00:00:00 2001
From: jiangpengfei <jiangpengfei9@huawei.com>
Date: Sat, 25 Jul 2020 09:22:08 +0800
Subject: [PATCH 02/50] kata-runtime: fix kata-runtime skip read lines in
 /proc/mounts file problem

reason: Since /proc/mounts is a virtual file which is changed dynamically by kernel,
if we use file pointer to read content in this file line by line, we may miss read
some lines. So we retry read /proc/mounts file again to fix this problem.

Signed-off-by: jiangpengfei <jiangpengfei9@huawei.com>
---
 virtcontainers/utils/utils_linux.go | 58 +++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 22 deletions(-)

diff --git a/virtcontainers/utils/utils_linux.go b/virtcontainers/utils/utils_linux.go
index ad870d63..6cef4cfb 100644
--- a/virtcontainers/utils/utils_linux.go
+++ b/virtcontainers/utils/utils_linux.go
@@ -7,15 +7,18 @@ package utils
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/rand"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math/big"
 	"os"
 	"strings"
 	"syscall"
 	"unsafe"
 
+	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
 )
 
@@ -93,6 +96,7 @@ const (
 	procMountsFile = "/proc/mounts"
 
 	fieldsPerLine = 6
+	maxRetryTimes = 5
 )
 
 const (
@@ -109,35 +113,45 @@ func GetDevicePathAndFsType(mountPoint string) (devicePath, fsType string, err e
 		return
 	}
 
-	var file *os.File
+	var retry int = 0
 
-	file, err = os.Open(procMountsFile)
-	if err != nil {
-		return
-	}
-
-	defer file.Close()
+	for retry <= maxRetryTimes {
+		var content []byte
 
-	reader := bufio.NewReader(file)
-	for {
-		var line string
-
-		line, err = reader.ReadString('\n')
-		if err == io.EOF {
-			err = fmt.Errorf("Mount %s not found", mountPoint)
+		content, err = ioutil.ReadFile(procMountsFile)
+		if err != nil {
 			return
 		}
 
-		fields := strings.Fields(line)
-		if len(fields) != fieldsPerLine {
-			err = fmt.Errorf("Incorrect no of fields (expected %d, got %d)) :%s", fieldsPerLine, len(fields), line)
-			return
+		bytesReader := bytes.NewReader(content)
+		reader := bufio.NewReader(bytesReader)
+
+		for {
+			var line string
+
+			line, err = reader.ReadString('\n')
+			if err == io.EOF {
+				err = fmt.Errorf("Mount %s not found", mountPoint)
+				break
+			}
+
+			fields := strings.Fields(line)
+			if len(fields) != fieldsPerLine {
+				err = fmt.Errorf("Incorrect no of fields (expected %d, got %d)) :%s", fieldsPerLine, len(fields), line)
+				return
+			}
+
+			if mountPoint == fields[procPathIndex] {
+				devicePath = fields[procDeviceIndex]
+				fsType = fields[procTypeIndex]
+				return
+			}
 		}
 
-		if mountPoint == fields[procPathIndex] {
-			devicePath = fields[procDeviceIndex]
-			fsType = fields[procTypeIndex]
-			return
+		retry = retry + 1
+		if retry <= maxRetryTimes {
+			logrus.Warnf("can not find %s in %s, retry %d times again......", mountPoint, procMountsFile, retry)
 		}
 	}
+	return "", "", fmt.Errorf("retry %d times fail to get devicePath adn fs type", maxRetryTimes)
 }
-- 
2.14.3 (Apple Git-98)

