mirror of https://gitee.com/openkylin/qemu.git
hw/9pfs: Proxy getversion
Add proxy getversion to get generation number Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
This commit is contained in:
parent
d52b09e475
commit
d090e452d4
|
@ -28,6 +28,11 @@
|
|||
#include <sys/vfs.h>
|
||||
#include <sys/stat.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#ifdef CONFIG_LINUX_MAGIC_H
|
||||
#include <linux/magic.h>
|
||||
#endif
|
||||
#include "qemu-common.h"
|
||||
#include "virtio-9p-marshal.h"
|
||||
#include "hw/9pfs/virtio-9p-proxy.h"
|
||||
|
@ -35,6 +40,19 @@
|
|||
|
||||
#define PROGNAME "virtfs-proxy-helper"
|
||||
|
||||
#ifndef XFS_SUPER_MAGIC
|
||||
#define XFS_SUPER_MAGIC 0x58465342
|
||||
#endif
|
||||
#ifndef EXT2_SUPER_MAGIC
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
#endif
|
||||
#ifndef REISERFS_SUPER_MAGIC
|
||||
#define REISERFS_SUPER_MAGIC 0x52654973
|
||||
#endif
|
||||
#ifndef BTRFS_SUPER_MAGIC
|
||||
#define BTRFS_SUPER_MAGIC 0x9123683E
|
||||
#endif
|
||||
|
||||
static struct option helper_opts[] = {
|
||||
{"fd", required_argument, NULL, 'f'},
|
||||
{"path", required_argument, NULL, 'p'},
|
||||
|
@ -42,6 +60,7 @@ static struct option helper_opts[] = {
|
|||
};
|
||||
|
||||
static bool is_daemon;
|
||||
static bool get_version; /* IOC getversion IOCTL supported */
|
||||
|
||||
static void do_log(int loglevel, const char *format, ...)
|
||||
{
|
||||
|
@ -330,6 +349,49 @@ static int send_response(int sock, struct iovec *iovec, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gets generation number
|
||||
* returns -errno on failure and sizeof(generation number) on success
|
||||
*/
|
||||
static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
|
||||
{
|
||||
uint64_t version;
|
||||
int retval = -ENOTTY;
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
int fd;
|
||||
V9fsString path;
|
||||
#endif
|
||||
|
||||
|
||||
/* no need to issue ioctl */
|
||||
if (!get_version) {
|
||||
version = 0;
|
||||
retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "q", version);
|
||||
return retval;
|
||||
}
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "s", &path);
|
||||
if (retval < 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
fd = open(path.data, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
retval = -errno;
|
||||
goto err_out;
|
||||
}
|
||||
if (ioctl(fd, FS_IOC_GETVERSION, &version) < 0) {
|
||||
retval = -errno;
|
||||
} else {
|
||||
retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "q", version);
|
||||
}
|
||||
close(fd);
|
||||
err_out:
|
||||
v9fs_string_free(&path);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
|
||||
{
|
||||
int size = 0, offset, retval;
|
||||
|
@ -673,6 +735,7 @@ static int process_reply(int sock, int type,
|
|||
case T_READLINK:
|
||||
case T_LGETXATTR:
|
||||
case T_LLISTXATTR:
|
||||
case T_GETVERSION:
|
||||
if (send_response(sock, out_iovec, retval) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -855,6 +918,9 @@ static int process_requests(int sock)
|
|||
v9fs_string_free(&path);
|
||||
v9fs_string_free(&name);
|
||||
break;
|
||||
case T_GETVERSION:
|
||||
retval = do_getversion(&in_iovec, &out_iovec);
|
||||
break;
|
||||
default:
|
||||
goto err_out;
|
||||
break;
|
||||
|
@ -876,6 +942,10 @@ int main(int argc, char **argv)
|
|||
char *rpath = NULL;
|
||||
struct stat stbuf;
|
||||
int c, option_index;
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
int retval;
|
||||
struct statfs st_fs;
|
||||
#endif
|
||||
|
||||
is_daemon = true;
|
||||
sock = -1;
|
||||
|
@ -932,6 +1002,22 @@ int main(int argc, char **argv)
|
|||
|
||||
do_log(LOG_INFO, "Started\n");
|
||||
|
||||
get_version = false;
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
/* check whether underlying FS support IOC_GETVERSION */
|
||||
retval = statfs(rpath, &st_fs);
|
||||
if (!retval) {
|
||||
switch (st_fs.f_type) {
|
||||
case EXT2_SUPER_MAGIC:
|
||||
case BTRFS_SUPER_MAGIC:
|
||||
case REISERFS_SUPER_MAGIC:
|
||||
case XFS_SUPER_MAGIC:
|
||||
get_version = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (chdir("/") < 0) {
|
||||
do_perror("chdir");
|
||||
goto error;
|
||||
|
|
|
@ -243,6 +243,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
|
|||
v9fs_string_free(&xattr);
|
||||
break;
|
||||
}
|
||||
case T_GETVERSION:
|
||||
proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -509,6 +512,14 @@ static int v9fs_request(V9fsProxy *proxy, int type,
|
|||
header.type = T_LREMOVEXATTR;
|
||||
}
|
||||
break;
|
||||
case T_GETVERSION:
|
||||
path = va_arg(ap, V9fsString *);
|
||||
retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
|
||||
if (retval > 0) {
|
||||
header.size = retval;
|
||||
header.type = T_GETVERSION;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_report("Invalid type %d\n", type);
|
||||
retval = -EINVAL;
|
||||
|
@ -559,6 +570,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
|
|||
case T_LSTAT:
|
||||
case T_READLINK:
|
||||
case T_STATFS:
|
||||
case T_GETVERSION:
|
||||
if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
|
||||
goto close_error;
|
||||
}
|
||||
|
@ -1064,6 +1076,25 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
|
||||
mode_t st_mode, uint64_t *st_gen)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Do not try to open special files like device nodes, fifos etc
|
||||
* we can get fd for regular files and directories only
|
||||
*/
|
||||
if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
|
||||
return 0;
|
||||
}
|
||||
err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path);
|
||||
if (err < 0) {
|
||||
errno = -err;
|
||||
err = -1;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
|
||||
{
|
||||
const char *sock_fd = qemu_opt_get(opts, "sock_fd");
|
||||
|
@ -1098,6 +1129,7 @@ static int proxy_init(FsContext *ctx)
|
|||
qemu_mutex_init(&proxy->mutex);
|
||||
|
||||
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
|
||||
ctx->exops.get_st_gen = proxy_ioc_getversion;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ enum {
|
|||
T_LLISTXATTR,
|
||||
T_LSETXATTR,
|
||||
T_LREMOVEXATTR,
|
||||
T_GETVERSION,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in New Issue