Skip to content

mount: handle loopback mount#4178

Closed
bergwolf wants to merge 2 commits intocontainerd:masterfrom
bergwolf:losetup
Closed

mount: handle loopback mount#4178
bergwolf wants to merge 2 commits intocontainerd:masterfrom
bergwolf:losetup

Conversation

@bergwolf
Copy link
Copy Markdown
Contributor

If a mount has specified loop option, we need to handle it on our
own instead of passing it to the kernel. In such case, create a
loopback device, attach the mount source to it, and mount the loopback
device rather than the mount source.

This is a spit from #3130 so that rawblock can be a non-builtin snapshotter.

/cc @dmcgowan @AkihiroSuda

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci Bot commented Apr 10, 2020

Build succeeded.

Comment thread mount/losetup_linux.go Outdated
@stevvooe
Copy link
Copy Markdown
Member

Would it be possible to reconcile this code with the other losetup code in containerd? https://github.com/containerd/containerd/search?q=losetup&unscoped_q=losetup provides some references. I didn't look into how similar they are.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci Bot commented Apr 14, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci Bot commented Apr 14, 2020

Build succeeded.

@bergwolf
Copy link
Copy Markdown
Contributor Author

@stevvooe I've implemented the same losetup APIs needed by devmapper, and replaced its private losetup command line wrapper with mount/losetup. PTAL.

@bergwolf
Copy link
Copy Markdown
Contributor Author

btw, the failed ci looks unrelated:

##[error]github.com/containerd/containerd/api/events/container.proto:6:1: warning: Import gogoproto/gogo.proto is unused.
##[error]github.com/containerd/containerd/api/events/namespace.proto:5:1: warning: Import gogoproto/gogo.proto is unused.
panic: protobuf tag not enough fields in FileDescriptorSet.state: 

@estesp
Copy link
Copy Markdown
Member

estesp commented Apr 14, 2020

We had a problem with unpinned dependencies breaking our protobuf checks in CI; if you can rebase on master HEAD, you should get a clean CI run now. Thanks!

Comment thread mount/losetup_linux.go Outdated
Comment thread mount/losetup_linux.go Outdated
Comment thread mount/losetup_linux.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the benefit of having this losetup code vs the old package ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The main purpose of the PR is to enable mount package to handle loopback mounts so that I can use it for the rawblock snapshotter. Maintainers also want to consolidate the two losetup implementation so I added the same APIs to replace the losetup command line wrappers. The main difference between them is calling the losetup binary or not.

Copy link
Copy Markdown
Member

@mxpv mxpv Apr 15, 2020

Choose a reason for hiding this comment

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

Sorry, I meant why not just reuse existing package. Potentially this one may be a lot harder to maintain and support, since Go is not the best fit for low level programming.

Copy link
Copy Markdown
Contributor Author

@bergwolf bergwolf Apr 15, 2020

Choose a reason for hiding this comment

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

Because it is not possible to create an autoclear loopback device with losetup command line. The workflow I want is:

  1. open the loop device
  2. set its backend and set the autoclear flag
  3. mount the loopback device with proper file system
  4. close the initial open file descriptor that we got in step 1

This is basically what you get with mount -o loop but it is not possible with the losetup command line. And the benefit is worthwhile -- we don't have to care about deleting the loopback device after unmounting the file system, nor if anything goes wrong in the middle before we mount the file system. The kernel takes care of cleaning up the loopback device once the last opener to it closes its open file descriptor.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

And we're already calling mount syscall instead of the mount binary in the mount package. Doing the same for loopback device follows the same philosophy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Because it is not possible to create an autoclear loopback device with losetup command line.

hm. As far as I understand losetup does that with --detach flag.

-d, --detach loopdev...
              Detach the file or device associated with the specified loop
              device(s). Note that since Linux v3.7 kernel uses "lazy device
              destruction".  The detach operation does not return EBUSY
              error anymore if device is actively used by system, but it is
              marked by autoclear flag and destroyed later.

http://man7.org/linux/man-pages/man8/losetup.8.html

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is the detach action, not setting a loop device as autoclear. With autoclear, the loop device is detached automatically after it is unmounted -- that means we do not need to call losetup -d after unmounting a loop device.

If we use losetup command line, the workflow is like:

  1. losetup -f <backing-file>
  2. mount with a file system
  3. unmount the file system
  4. losetup -d <loop-device>

Whereas with autoclear, we do:

  1. mount -o loop <backing-file> alike with mount package
  2. umount the file system

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Or do you mean that we should do the following?

  1. losetup -f <backing-file>
  2. mount with a file system
  3. losetup -d <loop-device>
  4. unmount the file system

That still doesn't look as neat as just doing

  1. mount -o loop <backing-file> alike with mount package
  2. umount the file system

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci Bot commented Apr 15, 2020

Build succeeded.

@bergwolf
Copy link
Copy Markdown
Contributor Author

@estesp Thanks for the hint. I've rebased on top of master.

If a mount has specified `loop` option, we need to handle it on our
own instead of passing it to the kernel. In such case, create a
loopback device, attach the mount source to it, and mount the loopback
device rather than the mount source.

Signed-off-by: Peng Tao <[email protected]>
No need to use the private losetup command line wrapper package.
The generic package provides the same functionality.

Signed-off-by: Peng Tao <[email protected]>
@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci Bot commented Apr 16, 2020

Build succeeded.

Copy link
Copy Markdown
Contributor

@zhsj zhsj left a comment

Choose a reason for hiding this comment

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

I think you don't need to define some magic values which are defined in golang.org/x/sys package.

Comment thread mount/losetup_linux.go
}

// struct loop_info64 in util-linux/include/loopdev.h
type loopInfo struct {
Copy link
Copy Markdown
Contributor

@zhsj zhsj May 21, 2020

Choose a reason for hiding this comment

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

Comment thread mount/losetup_linux.go
_ [112]byte
}

func ioctl(fd, req, args uintptr) (uintptr, uintptr, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe using Ioctl* family from golang.org/x/sys/unix?

Comment thread mount/losetup_linux.go
ioctlSetFd = 0x4C00
ioctlClrFd = 0x4C01
ioctlSetStatus64 = 0x4C04
ioctlGetFree = 0x4C82
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unix.LOOP_SET_FD
unix.LOOP_CLR_FD
unix.LOOP_SET_STATUS64
unix.LOOP_CTL_GET_FREE

Comment thread mount/losetup_linux.go
//loFlagsUseAops = 2
loFlagsAutoclear = 4
//loFlagsPartScan = 8
loFlagsDirectIO = 16
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unix.LO_FLAGS_READ_ONLY
unix.LO_FLAGS_AUTOCLEAR
unix.LO_FLAGS_PARTSCAN
unix.LO_FLAGS_DIRECT_IO

Comment thread mount/losetup_linux.go
//loFlagsPartScan = 8
loFlagsDirectIO = 16

ebusyString = "device or resource busy"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unix.EBUSY.Error() is this. But I think you don't need to compare the error string.

@mxpv
Copy link
Copy Markdown
Member

mxpv commented Jun 25, 2020

+1 for using existing routines from unix package. Could you possibly address that @bergwolf ?

@AkihiroSuda
Copy link
Copy Markdown
Member

ping @bergwolf

mxpv added a commit to mxpv/containerd that referenced this pull request Jan 4, 2021
@mxpv
Copy link
Copy Markdown
Member

mxpv commented Jan 8, 2021

Carried in #4902

@mxpv mxpv closed this Jan 8, 2021
@bergwolf bergwolf deleted the losetup branch November 7, 2022 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants