From 0e5fc994d24af4f4f9a1368bf9c2e730c120c549 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 28 Jan 2014 17:08:24 +0200 Subject: hw/9pfs: fix error handing in local_ioc_getversion() v9fs_co_st_gen() expects to see error code in errno, not in return code. Let's fix this. Signed-off-by: Kirill A. Shutemov Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p-local.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index fc93e9e..9be8854 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -1068,8 +1068,8 @@ err_out: static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { - int err; #ifdef FS_IOC_GETVERSION + int err; V9fsFidOpenState fid_open; /* @@ -1085,10 +1085,11 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, } err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); local_close(ctx, &fid_open); + return err; #else - err = -ENOTTY; + errno = ENOTTY; + return -1; #endif - return err; } static int local_init(FsContext *ctx) -- cgit v1.1 From b9317661d13230ec9fd1162625b7f812c0cacd37 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 28 Jan 2014 17:08:25 +0200 Subject: hw/9pfs: handle undefined FS_IOC_GETVERSION case in handle_ioc_getversion() All get_st_gen() implementations except handle_ioc_getversion() have guard for undefined FS_IOC_GETVERSION. Let's add it there too. Signed-off-by: Kirill A. Shutemov Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p-handle.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw') diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index fe8e0ed..ed8c126 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -582,6 +582,7 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir, static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { +#ifdef FS_IOC_GETVERSION int err; V9fsFidOpenState fid_open; @@ -599,6 +600,10 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); handle_close(ctx, &fid_open); return err; +#else + errno = ENOTTY; + return -1; +#endif } static int handle_init(FsContext *ctx) -- cgit v1.1 From 1a9978a51a17a26fd07e1b46f31ceeb9772fc191 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 28 Jan 2014 17:08:26 +0200 Subject: hw/9pfs: make get_st_gen() return ENOTTY error on special files Currently we silently ignore getversion requests for anything except file or directory. Let's instead return ENOTTY error to indicate that getversion is not supported. It makes implementation consistent on all not-supported cases. Signed-off-by: Kirill A. Shutemov Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p-handle.c | 3 ++- hw/9pfs/virtio-9p-local.c | 3 ++- hw/9pfs/virtio-9p-proxy.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index ed8c126..17002a3 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -591,7 +591,8 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, * We can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = handle_open(ctx, path, O_RDONLY, &fid_open); if (err < 0) { diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 9be8854..df0dbff 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -1077,7 +1077,8 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, * We can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = local_open(ctx, path, O_RDONLY, &fid_open); if (err < 0) { diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index 5f44bb7..b57966d 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -1086,7 +1086,8 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path, * we can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path); if (err < 0) { -- cgit v1.1 From f8b7ee38b3ed4ec2da5cc0529cf0cf82c8589805 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 28 Jan 2014 17:08:27 +0200 Subject: hw/9pfs: fix P9_STATS_GEN handling Currently we fail getattr request altogether if we can't read P9_STATS_GEN for some reason. It breaks valid use cases: E.g let's assume we have non-readable directory with execution bit set on host and we export it to client over 9p On host we can chdir into directory, but not open directory on read and list content. But if client will try to call getattr (as part of chdir(2)) for the directory it will fail with -EACCES. It happens because we try to open the directory on read to call ioctl(FS_IOC_GETVERSION), it fails and we return the error code to client. It's excessive. The solution is to make P9_STATS_GEN failure non-fatal for getattr request. Just don't set P9_STATS_GEN flag in result mask on failure. Signed-off-by: Kirill A. Shutemov Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofile.c | 4 ---- hw/9pfs/virtio-9p.c | 12 ++++++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 194c130..2efebf3 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -38,10 +38,6 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, }); v9fs_path_unlock(s); } - /* The ioctl may not be supported depending on the path */ - if (err == -ENOTTY) { - err = 0; - } return err; } diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 8cbb8ae..83e4e93 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1080,10 +1080,18 @@ static void v9fs_getattr(void *opaque) /* fill st_gen if requested and supported by underlying fs */ if (request_mask & P9_STATS_GEN) { retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl); - if (retval < 0) { + switch (retval) { + case 0: + /* we have valid st_gen: update result mask */ + v9stat_dotl.st_result_mask |= P9_STATS_GEN; + break; + case -EINTR: + /* request cancelled, e.g. by Tflush */ goto out; + default: + /* failed to get st_gen: not fatal, ignore */ + break; } - v9stat_dotl.st_result_mask |= P9_STATS_GEN; } retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl); if (retval < 0) { -- cgit v1.1