Commit f1b5618e authored by David Howells's avatar David Howells Committed by Al Viro

vfs: Add a sample program for the new mount API

Add a sample program to demonstrate fsopen/fsmount/move_mount to mount
something.

To make it compile on all arches, irrespective of whether or not syscall
numbers are assigned, define the syscall number to -1 if it isn't to cause
the kernel to return -ENOSYS.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cf3cba4a
...@@ -154,10 +154,11 @@ config SAMPLE_ANDROID_BINDERFS ...@@ -154,10 +154,11 @@ config SAMPLE_ANDROID_BINDERFS
Builds a sample program to illustrate the use of the Android binderfs Builds a sample program to illustrate the use of the Android binderfs
filesystem. filesystem.
config SAMPLE_STATX config SAMPLE_VFS
bool "Build example extended-stat using code" bool "Build example programs that use new VFS system calls"
depends on BROKEN
help 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 endif # SAMPLES
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
configfs/ connector/ v4l/ trace_printk/ \ configfs/ connector/ v4l/ trace_printk/ \
vfio-mdev/ statx/ qmi/ binderfs/ vfio-mdev/ vfs/ qmi/ binderfs/
# List of programs to build # 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 # Tell kbuild to always build the programs
always := $(hostprogs-y) always := $(hostprogs-y)
HOSTCFLAGS_test-fsmount.o += -I$(objtree)/usr/include
HOSTCFLAGS_test-statx.o += -I$(objtree)/usr/include HOSTCFLAGS_test-statx.o += -I$(objtree)/usr/include
/* 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 @@ ...@@ -25,13 +25,21 @@
#include <sys/types.h> #include <sys/types.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#define statx foo
#define statx_timestamp foo_timestamp
#include <sys/stat.h> #include <sys/stat.h>
#undef statx
#undef statx_timestamp
#define AT_STATX_SYNC_TYPE 0x6000 #define AT_STATX_SYNC_TYPE 0x6000
#define AT_STATX_SYNC_AS_STAT 0x0000 #define AT_STATX_SYNC_AS_STAT 0x0000
#define AT_STATX_FORCE_SYNC 0x2000 #define AT_STATX_FORCE_SYNC 0x2000
#define AT_STATX_DONT_SYNC 0x4000 #define AT_STATX_DONT_SYNC 0x4000
#ifndef __NR_statx
#define __NR_statx -1
#endif
static __attribute__((unused)) static __attribute__((unused))
ssize_t statx(int dfd, const char *filename, unsigned flags, ssize_t statx(int dfd, const char *filename, unsigned flags,
unsigned int mask, struct statx *buffer) unsigned int mask, struct statx *buffer)
...@@ -157,7 +165,8 @@ static void dump_statx(struct statx *stx) ...@@ -157,7 +165,8 @@ static void dump_statx(struct statx *stx)
"?dai?c??" /* 7- 0 0x00000000-000000ff */ "?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) { for (byte = 64 - 8; byte >= 0; byte -= 8) {
bits = stx->stx_attributes >> byte; bits = stx->stx_attributes >> byte;
mbits = stx->stx_attributes_mask >> byte; mbits = stx->stx_attributes_mask >> byte;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment