blob: ea28a9850f3070452b9906168c772d11e32b0023 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fs/vfs.h>
#include <fdio/debug.h>
#include <fdio/io.fidl2.h>
#include <fdio/remoteio.h>
#include <fdio/vfs.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
// Sends an 'unmount' signal on the srv handle, and waits until it is closed.
// Consumes 'srv'.
zx_status_t vfs_unmount_handle(zx_handle_t srv, zx_time_t deadline) {
// TODO(smklein): use shared ioctl impl?
#ifdef ZXRIO_FIDL
uint8_t msg[FIDL_ALIGN(sizeof(NodeIoctlRequest)) + FDIO_CHUNK_SIZE];
NodeIoctlRequest* request = (NodeIoctlRequest*) msg;
NodeIoctlResponse* response = (NodeIoctlResponse*) msg;
// the only other messages we ever send are no-reply OPEN or CLONE with
// txid of 0.
request->hdr.txid = 1;
request->hdr.ordinal = ZXFIDL_IOCTL;
request->opcode = IOCTL_VFS_UNMOUNT_FS;
request->max_out = 0;
request->handles.count = 0;
request->handles.data = (void*) FIDL_ALLOC_PRESENT;
request->in.count = 0;
request->in.data = (void*) FIDL_ALLOC_PRESENT;
zx_channel_call_args_t args;
args.wr_bytes = request;
args.wr_handles = NULL;
args.rd_bytes = response;
args.rd_handles = NULL;
args.wr_num_bytes = FIDL_ALIGN(sizeof(NodeIoctlRequest));
args.wr_num_handles = 0;
args.rd_num_bytes = FIDL_ALIGN(sizeof(NodeIoctlResponse));
args.rd_num_handles = 0;
uint32_t dsize;
uint32_t hcount;
zx_status_t rs;
// At the moment, we don't actually care what the response is from the
// filesystem server (or even if it supports the unmount operation). As
// soon as ANY response comes back, either in the form of a closed handle
// or a visible response, shut down.
zx_status_t status = zx_channel_call(srv, 0, deadline, &args, &dsize, &hcount, &rs);
if (status == ZX_ERR_CALL_FAILED) {
// Write phase succeeded. The target filesystem had a chance to unmount properly.
status = ZX_OK;
} else if (status == ZX_OK) {
// Read phase succeeded. If the target filesystem returned an error, we
// should parse it.
if (dsize < FIDL_ALIGN(sizeof(NodeIoctlResponse))) {
status = ZX_ERR_IO;
} else {
status = response->s;
}
}
#else
zxrio_msg_t msg;
memset(&msg, 0, ZXRIO_HDR_SZ);
// the only other messages we ever send are no-reply OPEN or CLONE with
// txid of 0.
msg.txid = 1;
msg.op = ZXRIO_IOCTL;
msg.arg2.op = IOCTL_VFS_UNMOUNT_FS;
zx_channel_call_args_t args;
args.wr_bytes = &msg;
args.wr_handles = NULL;
args.rd_bytes = &msg;
args.rd_handles = NULL;
args.wr_num_bytes = ZXRIO_HDR_SZ;
args.wr_num_handles = 0;
args.rd_num_bytes = ZXRIO_HDR_SZ + FDIO_CHUNK_SIZE;
args.rd_num_handles = 0;
uint32_t dsize;
uint32_t hcount;
zx_status_t rs;
// At the moment, we don't actually care what the response is from the
// filesystem server (or even if it supports the unmount operation). As
// soon as ANY response comes back, either in the form of a closed handle
// or a visible response, shut down.
zx_status_t status = zx_channel_call(srv, 0, deadline, &args, &dsize, &hcount, &rs);
if (status == ZX_ERR_CALL_FAILED) {
// Write phase succeeded. The target filesystem had a chance to unmount properly.
status = ZX_OK;
} else if (status == ZX_OK) {
// Read phase succeeded. If the target filesystem returned an error, we
// should parse it.
if (dsize < ZXRIO_HDR_SZ) {
status = ZX_ERR_IO;
} else {
status = msg.arg;
}
}
#endif
zx_handle_close(srv);
return status;
}