Browse code

devmapper: Fail to start container if xfs_nospace_max_retries can't be enforced

We just introduced a new tunable dm.xfs_nospace_max_retries. But this tunable
will work only on new kernels where xfs supports this feature. On older
kernels xfs does not allow tuning this behavior.

There are two issues. First one is that if xfsSetNospaceRetries() fails,
it returns error but leaves the device activated and mounted. We should
be unmounting the device and deactivate it before returning.

Second issue is, if docker is started on older kernel, with
dm.xfs_nospace_max_retries specified, then docker will silently ignore the
fact that /sys file to tweak this behavior is not present and will continue.
But I think it might be better to fail container creation/start if kernel
does not support this feature.

This patch fixes it. After this patch, user will get an error like following
when container is run.

# docker run -ti fedora bash
docker: Error response from daemon: devmapper: user specified daemon option dm.xfs_nospace_max_retries but it does not seem to be supported on this system :open /sys/fs/xfs/dm-5/error/metadata/ENOSPC/max_retries: no such file or directory.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>

Vivek Goyal authored on 2016/09/08 03:03:01
Showing 1 changed files
... ...
@@ -2325,11 +2325,7 @@ func (devices *DeviceSet) xfsSetNospaceRetries(info *devInfo) error {
2325 2325
 	filePath := "/sys/fs/xfs/" + dmDeviceName + "/error/metadata/ENOSPC/max_retries"
2326 2326
 	maxRetriesFile, err := os.OpenFile(filePath, os.O_WRONLY, 0)
2327 2327
 	if err != nil {
2328
-		// Older kernels don't have this feature/file
2329
-		if os.IsNotExist(err) {
2330
-			return nil
2331
-		}
2332
-		return fmt.Errorf("devmapper: Failed to open file %v:%v", filePath, err)
2328
+		return fmt.Errorf("devmapper: user specified daemon option dm.xfs_nospace_max_retries but it does not seem to be supported on this system :%v", err)
2333 2329
 	}
2334 2330
 	defer maxRetriesFile.Close()
2335 2331
 
... ...
@@ -2383,6 +2379,8 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
2383 2383
 
2384 2384
 	if fstype == "xfs" && devices.xfsNospaceRetries != "" {
2385 2385
 		if err := devices.xfsSetNospaceRetries(info); err != nil {
2386
+			syscall.Unmount(path, syscall.MNT_DETACH)
2387
+			devices.deactivateDevice(info)
2386 2388
 			return err
2387 2389
 		}
2388 2390
 	}