[PATCH] Fix mkdir syscall issue and implement mkdirat

40 views
Skip to first unread message

David Smith

unread,
Jan 12, 2021, 6:01:48 AM1/12/21
to osv...@googlegroups.com, David Smith
Signed-off-by: David Smith <d787...@gmail.com>
---
fs/vfs/main.cc | 36 ++++++++++++++++++++++++++++++++++++
fs/vfs/vfs.h | 1 +
fs/vfs/vfs_syscalls.cc | 27 +++++++++++++++++++++++++++
libc/syscall_to_function.h | 2 ++
linux.cc | 2 ++
5 files changed, 68 insertions(+)

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 55031380..12461995 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -833,6 +833,42 @@ mkdir(const char *pathname, mode_t mode)
return -1;
}

+TRACEPOINT(trace_vfs_mkdirat, "%d \"%s\" 0%0o", int, const char*, mode_t);
+TRACEPOINT(trace_vfs_mkdirat_ret, "");
+TRACEPOINT(trace_vfs_mkdirat_err, "%d", int);
+
+int
+mkdirat(int dfd, const char *pathname, mode_t mode)
+{
+ struct task *t = main_task;
+ char path[PATH_MAX];
+ int error;
+
+ mode = apply_umask(mode);
+
+ trace_vfs_mkdirat(dfd, pathname, mode);
+ if ('/' == path[0] || AT_FDCWD == dfd) {
+ // Supplied path is either absolute or relative to cwd
+ // Convert supplied path to a clean fully qualified path
+ if ((error = task_conv(t, pathname, VWRITE, path)) != 0)
+ goto out_errno;
+
+ error = sys_mkdir(path, mode);
+ } else {
+ // Supplied path is relative to folder specified by dfd
+ error = sys_mkdirat(dfd, path, mode);
+ }
+
+ if (error)
+ goto out_errno;
+ trace_vfs_mkdirat_ret();
+ return 0;
+ out_errno:
+ trace_vfs_mkdirat_err(error);
+ errno = error;
+ return -1;
+}
+
TRACEPOINT(trace_vfs_rmdir, "\"%s\"", const char*);
TRACEPOINT(trace_vfs_rmdir_ret, "");
TRACEPOINT(trace_vfs_rmdir_err, "%d", int);
diff --git a/fs/vfs/vfs.h b/fs/vfs/vfs.h
index d86ef957..3fe3ae22 100644
--- a/fs/vfs/vfs.h
+++ b/fs/vfs/vfs.h
@@ -106,6 +106,7 @@ int sys_telldir(struct file *fp, long *loc);
int sys_fchdir(struct file *fp, char *path);

int sys_mkdir(char *path, mode_t mode);
+int sys_mkdirat(int dfd, char *path, mode_t mode);
int sys_rmdir(char *path);
int sys_mknod(char *path, mode_t mode);
int sys_rename(char *src, char *dest);
diff --git a/fs/vfs/vfs_syscalls.cc b/fs/vfs/vfs_syscalls.cc
index cd0d1745..aae6b037 100644
--- a/fs/vfs/vfs_syscalls.cc
+++ b/fs/vfs/vfs_syscalls.cc
@@ -547,6 +547,33 @@ sys_mkdir(char *path, mode_t mode)
return error;
}

+int
+sys_mkdirat(int dfd, char *path, mode_t mode)
+{
+ struct file *fp;
+ int error = fget(dfd, &fp);
+ if (error)
+ return error;
+
+ struct vnode *vp = fp->f_dentry->d_vnode;
+ vn_lock(vp);
+
+ std::unique_ptr<char []> up (new char[PATH_MAX]);
+ char *p = up.get();
+
+ /* build absolute path */
+ strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX);
+ strlcat(p, fp->f_dentry->d_path, PATH_MAX);
+ strlcat(p, "/", PATH_MAX);
+ strlcat(p, path, PATH_MAX);
+
+ vn_unlock(vp);
+ fdrop(fp);
+
+ error = sys_mkdir(p, mode);
+ return error;
+}
+
int
sys_rmdir(char *path)
{
diff --git a/libc/syscall_to_function.h b/libc/syscall_to_function.h
index 73525cfa..6862fe34 100644
--- a/libc/syscall_to_function.h
+++ b/libc/syscall_to_function.h
@@ -19,6 +19,8 @@
#define __OSV_TO_FUNCTION_SYS_writev writev
#define __OSV_TO_FUNCTION_SYS_fstatat fstatat
#define __OSV_TO_FUNCTION_SYS_unlinkat unlinkat
+#define __OSV_TO_FUNCTION_SYS_mkdir mkdir
+#define __OSV_TO_FUNCTION_SYS_mkdirat mkdirat

#undef __syscall
#define __syscall(sys_number, ...) (__OSV_TO_FUNCTION_##sys_number(__VA_ARGS__) < 0 ? -errno : 0)
diff --git a/linux.cc b/linux.cc
index 6eb9d3fe..71ec8da1 100644
--- a/linux.cc
+++ b/linux.cc
@@ -447,6 +447,8 @@ long syscall(long number, ...)
SYSCALL0(getpid);
SYSCALL3(set_mempolicy, int, unsigned long *, unsigned long);
SYSCALL3(sched_setaffinity_syscall, pid_t, unsigned, unsigned long *);
+ SYSCALL2(mkdir, char*, mode_t);
+ SYSCALL3(mkdirat, int, char*, mode_t);
}

debug_always("syscall(): unimplemented system call %d\n", number);
--
2.25.1

Nadav Har'El

unread,
Jan 12, 2021, 6:49:17 AM1/12/21
to David Smith, Osv Dev
I think you have a typo here - you need to check "pathname" (the parameter), not "path" (the temporary array which you didn't initialize yet).

+        // Supplied path is either absolute or relative to cwd
+        // Convert supplied path to a clean fully qualified path
+        if ((error = task_conv(t, pathname, VWRITE, path)) != 0)
+            goto out_errno;
+   
+        error = sys_mkdir(path, mode);
+    } else {
+        // Supplied path is relative to folder specified by dfd
+        error = sys_mkdirat(dfd, path, mode);

Again, shouldn't this be pathmame?

--
You received this message because you are subscribed to the Google Groups "OSv Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20210112110138.28828-1-d7878291%40gmail.com.

David Smith

unread,
Jan 12, 2021, 7:16:14 AM1/12/21
to OSv Development
Yes, quite right. My bad. I've corrected those and all 5 test cases are now passing. Thanks. V2 patch on the way soon. 

David Smith

unread,
Jan 12, 2021, 8:36:50 AM1/12/21
to OSv Development
v2 patch submitted.

David Smith

unread,
Jan 15, 2021, 8:34:44 AM1/15/21
to osv...@googlegroups.com, David Smith
Signed-off-by: David Smith <d787...@gmail.com>
---
fs/vfs/main.cc | 37 +++++++++++++++++++++++++++++++++++++
libc/syscall_to_function.h | 2 ++
linux.cc | 2 ++
3 files changed, 41 insertions(+)

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 55031380..71110796 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -833,6 +833,43 @@ mkdir(const char *pathname, mode_t mode)
return -1;
}

+int mkdirat(int dirfd, const char *pathname, mode_t mode)
+{
+ mode = apply_umask(mode);
+
+ if (pathname[0] == '/' || dirfd == AT_FDCWD) {
+ // Supplied path is either absolute or relative to cwd
+ return mkdir(pathname, mode);
+ }
+
+ // Supplied path is relative to folder specified by dirfd
+ struct file *fp;
+ int error = fget(dirfd, &fp);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ struct vnode *vp = fp->f_dentry->d_vnode;
+ vn_lock(vp);
+
+ std::unique_ptr<char []> up (new char[PATH_MAX]);
+ char *p = up.get();
+
+ /* build absolute path */
+ strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX);
+ strlcat(p, fp->f_dentry->d_path, PATH_MAX);
+ strlcat(p, "/", PATH_MAX);
+ strlcat(p, pathname, PATH_MAX);
+
+ error = mkdir(p, mode);
+
+ vn_unlock(vp);
+ fdrop(fp);
+
+ return error;
+}
+
TRACEPOINT(trace_vfs_rmdir, "\"%s\"", const char*);
TRACEPOINT(trace_vfs_rmdir_ret, "");
TRACEPOINT(trace_vfs_rmdir_err, "%d", int);

Commit Bot

unread,
Jan 18, 2021, 1:00:21 PM1/18/21
to osv...@googlegroups.com, David Smith
From: David Smith <d787...@gmail.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

Fix mkdir syscall issue and implement mkdirat

Signed-off-by: David Smith <d787...@gmail.com>
Message-Id: <20210115133359.1...@gmail.com>

---
diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
--- a/libc/syscall_to_function.h
+++ b/libc/syscall_to_function.h
@@ -19,6 +19,8 @@
#define __OSV_TO_FUNCTION_SYS_writev writev
#define __OSV_TO_FUNCTION_SYS_fstatat fstatat
#define __OSV_TO_FUNCTION_SYS_unlinkat unlinkat
+#define __OSV_TO_FUNCTION_SYS_mkdir mkdir
+#define __OSV_TO_FUNCTION_SYS_mkdirat mkdirat

#undef __syscall
#define __syscall(sys_number, ...) (__OSV_TO_FUNCTION_##sys_number(__VA_ARGS__) < 0 ? -errno : 0)
diff --git a/linux.cc b/linux.cc

Waldek Kozaczuk

unread,
Jan 19, 2021, 11:51:25 AM1/19/21
to OSv Development

Nadav,

I think you applied the wrong version of the patch. I think you meant to apply the latest from "Jan 15, 2021, 8:34:44 AM (4 days ago)", no?

Waldek

Waldek Kozaczuk

unread,
Jan 19, 2021, 5:33:59 PM1/19/21
to OSv Development
Nevermind. You applied the correct one.
Reply all
Reply to author
Forward
0 new messages