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: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
cf3cba4a42
commit
f1b5618e01
@ -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 @@
|
|||||||
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/
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
# 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
|
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 <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)
|
|||||||
"?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;
|
Loading…
Reference in New Issue
Block a user