diff --git a/src/lua/fio.lua b/src/lua/fio.lua
index 48687703bdfb83e2fc42e2debde74c4815949ab9..9f6b10d92fa7efefd86f443c2c1862829b144aa0 100644
--- a/src/lua/fio.lua
+++ b/src/lua/fio.lua
@@ -5,6 +5,7 @@ local ffi = require('ffi')
 
 ffi.cdef[[
     int umask(int mask);
+    char *dirname(char *path);
 ]]
 
 local internal = fio.internal
@@ -209,18 +210,8 @@ fio.dirname = function(path)
         return nil
     end
     path = tostring(path)
-
-    while true do
-        if path == "" or string.sub(path, -1) == "/" then
-            break
-        end
-        path = string.sub(path, 1, -2)
-    end
-    if path == "" then
-        path = "."
-    end
-
-    return path
+    path = ffi.new('char[?]', #path, path)
+    return ffi.string(ffi.C.dirname(path))
 end
 
 fio.umask = function(umask)
diff --git a/test/box/fio.result b/test/box/fio.result
index 1485c63ad1689a6263814b9a4919af3b1314692a..301874a6dfd5bcae89e7bac05406b7f1f0306d51 100644
--- a/test/box/fio.result
+++ b/test/box/fio.result
@@ -286,3 +286,24 @@ fio.unlink(nil)
 ---
 - false
 ...
+-- dirname
+fio.dirname('abc')
+---
+- .
+...
+fio.dirname('/abc')
+---
+- /
+...
+fio.dirname('/abc/cde')
+---
+- /abc
+...
+fio.dirname('/abc/cde/')
+---
+- /abc
+...
+fio.dirname('/')
+---
+- /
+...
diff --git a/test/box/fio.test.lua b/test/box/fio.test.lua
index c97c15965a5d0f12d9d25e1c279a69bb2e5c0d54..2a18ee6df2479a0d0f98c6b6cf1c2907b76460ab 100644
--- a/test/box/fio.test.lua
+++ b/test/box/fio.test.lua
@@ -97,3 +97,11 @@ fio.rmdir(tmpdir)
 
 fio.unlink()
 fio.unlink(nil)
+
+-- dirname
+
+fio.dirname('abc')
+fio.dirname('/abc')
+fio.dirname('/abc/cde')
+fio.dirname('/abc/cde/')
+fio.dirname('/')