diff --git a/fs/failfs.c b/fs/failfs.c index d0ca1fc6c459..66a36da3d236 100644 --- a/fs/failfs.c +++ b/fs/failfs.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,16 @@ static int failfs_init_fs_context(struct fs_context *fc) return 0; } +int failfs_current_chdir(void) +{ + struct path path; + + failfs_get_root(&path); + set_fs_pwd(current->fs, &path); + path_put(&path); + return 0; +} + static struct file_system_type failfs_fs_type = { .name = "failfs", .init_fs_context = failfs_init_fs_context, diff --git a/fs/internal.h b/fs/internal.h index ce7f12c5a65b..67aa0444351b 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -365,3 +365,4 @@ void nsfs_get_root(struct path *path); void failfs_get_root(struct path *path); void __init failfs_init(void); bool failfs_mnt(const struct vfsmount *mnt); +int failfs_current_chdir(void); diff --git a/fs/open.c b/fs/open.c index 408925d7bd0b..56b6032d4d81 100644 --- a/fs/open.c +++ b/fs/open.c @@ -570,9 +570,12 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename) SYSCALL_DEFINE1(fchdir, unsigned int, fd) { - CLASS(fd_raw, f)(fd); int error; + if ((int)fd == FD_FAILFS_ROOT) + return failfs_current_chdir(); + + CLASS(fd_raw, f)(fd); if (fd_empty(f)) return -EBADF; diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index aadfbf6e0cb3..e43e3de3e9ee 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h @@ -124,6 +124,7 @@ struct delegation { #define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */ #define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */ +#define FD_FAILFS_ROOT -10004 /* Root of the failfs filesystem */ #define FD_INVALID -10009 /* Invalid file descriptor: -10000 - EBADF = -10009 */ /* Generic flags for the *at(2) family of syscalls. */