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>
这个提交包含在:
133
samples/vfs/test-fsmount.c
普通文件
133
samples/vfs/test-fsmount.c
普通文件
@@ -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);
|
||||
}
|
在新工单中引用
屏蔽一个用户