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:
M. Mohan Kumar 2011-12-14 13:58:46 +05:30 committed by Aneesh Kumar K.V
parent d52b09e475
commit d090e452d4
3 changed files with 119 additions and 0 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -58,6 +58,7 @@ enum {
T_LLISTXATTR,
T_LSETXATTR,
T_LREMOVEXATTR,
T_GETVERSION,
};
typedef struct {