mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-08 01:52:41 +00:00
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/vfs.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <attr/xattr.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 "qemu-common.h"
|
||||||
#include "virtio-9p-marshal.h"
|
#include "virtio-9p-marshal.h"
|
||||||
#include "hw/9pfs/virtio-9p-proxy.h"
|
#include "hw/9pfs/virtio-9p-proxy.h"
|
||||||
@ -35,6 +40,19 @@
|
|||||||
|
|
||||||
#define PROGNAME "virtfs-proxy-helper"
|
#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[] = {
|
static struct option helper_opts[] = {
|
||||||
{"fd", required_argument, NULL, 'f'},
|
{"fd", required_argument, NULL, 'f'},
|
||||||
{"path", required_argument, NULL, 'p'},
|
{"path", required_argument, NULL, 'p'},
|
||||||
@ -42,6 +60,7 @@ static struct option helper_opts[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static bool is_daemon;
|
static bool is_daemon;
|
||||||
|
static bool get_version; /* IOC getversion IOCTL supported */
|
||||||
|
|
||||||
static void do_log(int loglevel, const char *format, ...)
|
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;
|
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)
|
static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
|
||||||
{
|
{
|
||||||
int size = 0, offset, retval;
|
int size = 0, offset, retval;
|
||||||
@ -673,6 +735,7 @@ static int process_reply(int sock, int type,
|
|||||||
case T_READLINK:
|
case T_READLINK:
|
||||||
case T_LGETXATTR:
|
case T_LGETXATTR:
|
||||||
case T_LLISTXATTR:
|
case T_LLISTXATTR:
|
||||||
|
case T_GETVERSION:
|
||||||
if (send_response(sock, out_iovec, retval) < 0) {
|
if (send_response(sock, out_iovec, retval) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -855,6 +918,9 @@ static int process_requests(int sock)
|
|||||||
v9fs_string_free(&path);
|
v9fs_string_free(&path);
|
||||||
v9fs_string_free(&name);
|
v9fs_string_free(&name);
|
||||||
break;
|
break;
|
||||||
|
case T_GETVERSION:
|
||||||
|
retval = do_getversion(&in_iovec, &out_iovec);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto err_out;
|
goto err_out;
|
||||||
break;
|
break;
|
||||||
@ -876,6 +942,10 @@ int main(int argc, char **argv)
|
|||||||
char *rpath = NULL;
|
char *rpath = NULL;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
int c, option_index;
|
int c, option_index;
|
||||||
|
#ifdef FS_IOC_GETVERSION
|
||||||
|
int retval;
|
||||||
|
struct statfs st_fs;
|
||||||
|
#endif
|
||||||
|
|
||||||
is_daemon = true;
|
is_daemon = true;
|
||||||
sock = -1;
|
sock = -1;
|
||||||
@ -932,6 +1002,22 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
do_log(LOG_INFO, "Started\n");
|
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) {
|
if (chdir("/") < 0) {
|
||||||
do_perror("chdir");
|
do_perror("chdir");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -243,6 +243,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
|
|||||||
v9fs_string_free(&xattr);
|
v9fs_string_free(&xattr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case T_GETVERSION:
|
||||||
|
proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -509,6 +512,14 @@ static int v9fs_request(V9fsProxy *proxy, int type,
|
|||||||
header.type = T_LREMOVEXATTR;
|
header.type = T_LREMOVEXATTR;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
error_report("Invalid type %d\n", type);
|
error_report("Invalid type %d\n", type);
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
@ -559,6 +570,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
|
|||||||
case T_LSTAT:
|
case T_LSTAT:
|
||||||
case T_READLINK:
|
case T_READLINK:
|
||||||
case T_STATFS:
|
case T_STATFS:
|
||||||
|
case T_GETVERSION:
|
||||||
if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
|
if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
|
||||||
goto close_error;
|
goto close_error;
|
||||||
}
|
}
|
||||||
@ -1064,6 +1076,25 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||||||
return ret;
|
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)
|
static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
|
||||||
{
|
{
|
||||||
const char *sock_fd = qemu_opt_get(opts, "sock_fd");
|
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);
|
qemu_mutex_init(&proxy->mutex);
|
||||||
|
|
||||||
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
|
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
|
||||||
|
ctx->exops.get_st_gen = proxy_ioc_getversion;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ enum {
|
|||||||
T_LLISTXATTR,
|
T_LLISTXATTR,
|
||||||
T_LSETXATTR,
|
T_LSETXATTR,
|
||||||
T_LREMOVEXATTR,
|
T_LREMOVEXATTR,
|
||||||
|
T_GETVERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user