Skip to content

bugfix: fetch the right device number which great than 255 #39212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2019

Conversation

yyb196
Copy link
Contributor

@yyb196 yyb196 commented May 14, 2019

Signed-off-by: frankyang yyb196@gmail.com

- What I did

fix a bug which cause an error like :
write 4349:48 0 to blkio.throttle.read_bps_device: write /sys/fs/cgroup/blkio/xxx/cid/blkio.throttle.read_bps_device: no such device

the container has config "BlkioDeviceReadBps":[{"Path":"/dev/vdt","Rate":0}]

and I foud stat /dev/vdt and ls -l /dev/vdt has different out of device number, which is correct:


#ls -l /dev/vdt
brw-rw---- 1 root disk 253, 304 May 9 17:03 /dev/vdt

#stat /dev/vdt | grep type
Device: 6h/6d Inode: 56051004	Links: 1	Device type: fd, 130

Someone in docker forum ran into the same problem: https://forums.docker.com/t/docker-run-device-read-bps-option-not-working/68044 in his case is the major number greater than 255.

- How I did it
I correct the way in which we get major and minor device number according to the method new_encode_dev in linux kernel.

- How to verify it
I add two unit test cases.

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

@olljanat
Copy link
Contributor

olljanat commented May 14, 2019

(reserved for my derek commands)

@olljanat
Copy link
Contributor

@yyb196 congrats of your first PR to moby 🎂

I'm not familiar this this feature so just to verify that did you test that those unit tests would fail without this fix?

@thaJeztah
Copy link
Member

ping @kolyshkin PTAL

@kolyshkin
Copy link
Contributor

Looks fine, but since x/sys/unix already implemented these, it'll be better to use those. In other words:

import "golang.org/x/sys/unix"
...
d.Major = unix.Major(stat.Rdev)
d.Minor = unix.Minor(stat.Rdev)

@yyb196 can you please update this PR?

@codecov
Copy link

codecov bot commented May 15, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@34b5672). Click here to learn what that means.
The diff coverage is 100%.

@@            Coverage Diff            @@
##             master   #39212   +/-   ##
=========================================
  Coverage          ?   37.06%           
=========================================
  Files             ?      612           
  Lines             ?    45494           
  Branches          ?        0           
=========================================
  Hits              ?    16862           
  Misses            ?    26344           
  Partials          ?     2288

@yyb196
Copy link
Contributor Author

yyb196 commented May 15, 2019

@kolyshkin @olljanat I have change the code and test case according to your advices.

PTALA, thanks a lot.

Using the unix package's methods Major and Minor.

And now the unit test case that I add will fail without this fix.

Because I don't know how to mock system call in go, my test case depends on that we can do unix.Mknode in unit test, then can I mock a temporary device whose major and minor device type great than 255.

@@ -376,3 +379,75 @@ func sysInfo(t *testing.T, opts ...func(*sysinfo.SysInfo)) sysinfo.SysInfo {
}
return si
}

func TestGetBlkioWeightDevices(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mknod requires root, so this test case should have something like

        if os.Getuid() != 0 {
                t.Skip("root required") // for mknod
        }

at the very beginning (so if someone runs go test as non-root, there won't be a fake failure).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, make sense to use

t.Parallel()


// mock a file with major 0x1FD(509 in decimal) and minor 0x130(304)
if err = unix.Mknod(tempFile, unix.S_IFCHR, 0x11FD30); err != nil {
t.Fatalf("mknode error %s(%x): %v", tempFile, 0x11FD30, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/mknode/mknod/

defer os.RemoveAll(tempDir)

// mock a file with major 0x1FD(509 in decimal) and minor 0x130(304)
if err = unix.Mknod(tempFile, unix.S_IFCHR, 0x11FD30); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use unix.Mkdev(major, minor) (and define major and minor as constants to not have some "magic numbers" across the code.

weightDevs, err := getBlkioWeightDevices(mockResource)
assert.NilError(t, err, "getBlkioWeightDevices")

if len(weightDevs) != 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert.Check(t, is.Len(weightDevs, 1), "getBlkioWeightDevices")

(you can use assert in other places in your code as well, it makes the code more compact and perhaps more readable)

@@ -376,3 +379,75 @@ func sysInfo(t *testing.T, opts ...func(*sysinfo.SysInfo)) sysinfo.SysInfo {
}
return si
}

func TestGetBlkioWeightDevices(t *testing.T) {
tempDir, err := ioutil.TempDir("", "tempDevDirForBlkioThrottleDevices")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/"tempDevDirForBlkioThrottleDevices"/t.Name()/

Copy link
Contributor

@kolyshkin kolyshkin May 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or, if you like it more, "tempDevDir"+t.Name()

}
}

func TestGetBlkioThrottleDevices(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This second test is the same as the first one, except for function called. Can you please combine the code so it won't repeat twice?

@kolyshkin
Copy link
Contributor

@yyb196 thanks so much for the update! I have left some comments

Signed-off-by: frankyang <yyb196@gmail.com>
@yyb196
Copy link
Contributor Author

yyb196 commented May 16, 2019

@kolyshkin thanks for your comments, I have updated. PTALA.

Copy link
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for good work!

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants