Merge branch 'work.mount-syscalls' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull mount ABI updates from Al Viro: "The syscalls themselves, finally. That's not all there is to that stuff, but switching individual filesystems to new methods is fortunately independent from everything else, so e.g. NFS series can go through NFS tree, etc. As those conversions get done, we'll be finally able to get rid of a bunch of duplication in fs/super.c introduced in the beginning of the entire thing. I expect that to be finished in the next window..." * 'work.mount-syscalls' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: vfs: Add a sample program for the new mount API vfs: syscall: Add fspick() to select a superblock for reconfiguration vfs: syscall: Add fsmount() to create a mount for a superblock vfs: syscall: Add fsconfig() for configuring and managing a context vfs: Implement logging through fs_context vfs: syscall: Add fsopen() to prepare for superblock creation Make anon_inodes unconditional teach move_mount(2) to work with OPEN_TREE_CLONE vfs: syscall: Add move_mount(2) to move mounts around vfs: syscall: Add open_tree(2) to reference or clone a mount
This commit is contained in:
@@ -154,10 +154,11 @@ config SAMPLE_ANDROID_BINDERFS
|
||||
Builds a sample program to illustrate the use of the Android binderfs
|
||||
filesystem.
|
||||
|
||||
config SAMPLE_STATX
|
||||
bool "Build example extended-stat using code"
|
||||
depends on BROKEN
|
||||
config SAMPLE_VFS
|
||||
bool "Build example programs that use new VFS system calls"
|
||||
help
|
||||
Build example userspace program to use the new extended-stat syscall.
|
||||
Build example userspace programs that use new VFS system calls such
|
||||
as mount API and statx(). Note that this is restricted to the x86
|
||||
arch whilst it accesses system calls that aren't yet in all arches.
|
||||
|
||||
endif # SAMPLES
|
||||
|
@@ -3,4 +3,4 @@
|
||||
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
|
||||
hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
|
||||
configfs/ connector/ v4l/ trace_printk/ \
|
||||
vfio-mdev/ statx/ qmi/ binderfs/ pidfd/
|
||||
vfio-mdev/ vfs/ qmi/ binderfs/ pidfd/
|
||||
|
@@ -1,7 +1,10 @@
|
||||
# List of programs to build
|
||||
hostprogs-$(CONFIG_SAMPLE_STATX) := test-statx
|
||||
hostprogs-$(CONFIG_SAMPLE_VFS) := \
|
||||
test-fsmount \
|
||||
test-statx
|
||||
|
||||
# Tell kbuild to always build the programs
|
||||
always := $(hostprogs-y)
|
||||
|
||||
HOSTCFLAGS_test-fsmount.o += -I$(objtree)/usr/include
|
||||
HOSTCFLAGS_test-statx.o += -I$(objtree)/usr/include
|
133
samples/vfs/test-fsmount.c
Normal file
133
samples/vfs/test-fsmount.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* fd-based mount test.
|
||||
*
|
||||
* Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the Licence, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0)
|
||||
|
||||
static void check_messages(int fd)
|
||||
{
|
||||
char buf[4096];
|
||||
int err, n;
|
||||
|
||||
err = errno;
|
||||
|
||||
for (;;) {
|
||||
n = read(fd, buf, sizeof(buf));
|
||||
if (n < 0)
|
||||
break;
|
||||
n -= 2;
|
||||
|
||||
switch (buf[0]) {
|
||||
case 'e':
|
||||
fprintf(stderr, "Error: %*.*s\n", n, n, buf + 2);
|
||||
break;
|
||||
case 'w':
|
||||
fprintf(stderr, "Warning: %*.*s\n", n, n, buf + 2);
|
||||
break;
|
||||
case 'i':
|
||||
fprintf(stderr, "Info: %*.*s\n", n, n, buf + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errno = err;
|
||||
}
|
||||
|
||||
static __attribute__((noreturn))
|
||||
void mount_error(int fd, const char *s)
|
||||
{
|
||||
check_messages(fd);
|
||||
fprintf(stderr, "%s: %m\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Hope -1 isn't a syscall */
|
||||
#ifndef __NR_fsopen
|
||||
#define __NR_fsopen -1
|
||||
#endif
|
||||
#ifndef __NR_fsmount
|
||||
#define __NR_fsmount -1
|
||||
#endif
|
||||
#ifndef __NR_fsconfig
|
||||
#define __NR_fsconfig -1
|
||||
#endif
|
||||
#ifndef __NR_move_mount
|
||||
#define __NR_move_mount -1
|
||||
#endif
|
||||
|
||||
|
||||
static inline int fsopen(const char *fs_name, unsigned int flags)
|
||||
{
|
||||
return syscall(__NR_fsopen, fs_name, flags);
|
||||
}
|
||||
|
||||
static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
|
||||
{
|
||||
return syscall(__NR_fsmount, fsfd, flags, ms_flags);
|
||||
}
|
||||
|
||||
static inline int fsconfig(int fsfd, unsigned int cmd,
|
||||
const char *key, const void *val, int aux)
|
||||
{
|
||||
return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
|
||||
}
|
||||
|
||||
static inline int move_mount(int from_dfd, const char *from_pathname,
|
||||
int to_dfd, const char *to_pathname,
|
||||
unsigned int flags)
|
||||
{
|
||||
return syscall(__NR_move_mount,
|
||||
from_dfd, from_pathname,
|
||||
to_dfd, to_pathname, flags);
|
||||
}
|
||||
|
||||
#define E_fsconfig(fd, cmd, key, val, aux) \
|
||||
do { \
|
||||
if (fsconfig(fd, cmd, key, val, aux) == -1) \
|
||||
mount_error(fd, key ?: "create"); \
|
||||
} while (0)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fsfd, mfd;
|
||||
|
||||
/* Mount a publically available AFS filesystem */
|
||||
fsfd = fsopen("afs", 0);
|
||||
if (fsfd == -1) {
|
||||
perror("fsopen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
E_fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "#grand.central.org:root.cell.", 0);
|
||||
E_fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
|
||||
|
||||
mfd = fsmount(fsfd, 0, MOUNT_ATTR_RDONLY);
|
||||
if (mfd < 0)
|
||||
mount_error(fsfd, "fsmount");
|
||||
E(close(fsfd));
|
||||
|
||||
if (move_mount(mfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH) < 0) {
|
||||
perror("move_mount");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
E(close(mfd));
|
||||
exit(0);
|
||||
}
|
@@ -25,13 +25,21 @@
|
||||
#include <sys/types.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/fcntl.h>
|
||||
#define statx foo
|
||||
#define statx_timestamp foo_timestamp
|
||||
#include <sys/stat.h>
|
||||
#undef statx
|
||||
#undef statx_timestamp
|
||||
|
||||
#define AT_STATX_SYNC_TYPE 0x6000
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000
|
||||
#define AT_STATX_FORCE_SYNC 0x2000
|
||||
#define AT_STATX_DONT_SYNC 0x4000
|
||||
|
||||
#ifndef __NR_statx
|
||||
#define __NR_statx -1
|
||||
#endif
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t statx(int dfd, const char *filename, unsigned flags,
|
||||
unsigned int mask, struct statx *buffer)
|
||||
@@ -157,7 +165,8 @@ static void dump_statx(struct statx *stx)
|
||||
"?dai?c??" /* 7- 0 0x00000000-000000ff */
|
||||
;
|
||||
|
||||
printf("Attributes: %016llx (", stx->stx_attributes);
|
||||
printf("Attributes: %016llx (",
|
||||
(unsigned long long)stx->stx_attributes);
|
||||
for (byte = 64 - 8; byte >= 0; byte -= 8) {
|
||||
bits = stx->stx_attributes >> byte;
|
||||
mbits = stx->stx_attributes_mask >> byte;
|
مرجع در شماره جدید
Block a user