mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +08:00
v9fs:socket driver
Summary: 1.Add new api for socket parsing header - v9fs_parse_size 2.Add socket driver for 9pfs Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
@@ -27,5 +27,9 @@ if(CONFIG_FS_V9FS)
|
||||
list(APPEND V9FS virtio_9p.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_V9FS_SOCKET_9P)
|
||||
list(APPEND V9FS socket_9p.c)
|
||||
endif()
|
||||
|
||||
target_sources(fs PRIVATE ${V9FS})
|
||||
endif()
|
||||
|
||||
@@ -21,4 +21,9 @@ config V9FS_VIRTIO_9P
|
||||
depends on DRIVERS_VIRTIO
|
||||
default n
|
||||
|
||||
config V9FS_SOCKET_9P
|
||||
bool "Socket 9P support"
|
||||
depends on NET_TCP
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
@@ -25,6 +25,10 @@ ifeq ($(CONFIG_FS_V9FS),y)
|
||||
|
||||
CSRCS += client.c transport.c v9fs.c
|
||||
|
||||
ifeq ($(CONFIG_V9FS_SOCKET_9P),y)
|
||||
CSRCS += socket_9p.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_V9FS_VIRTIO_9P),y)
|
||||
CSRCS += virtio_9p.c
|
||||
endif
|
||||
|
||||
@@ -1811,3 +1811,13 @@ int v9fs_fid_get(FAR struct v9fs_client_s *client, uint32_t fid)
|
||||
nxmutex_unlock(&client->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* v9fs_parse_size
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t v9fs_parse_size(FAR const void *buffer)
|
||||
{
|
||||
FAR const struct v9fs_header_s *ptr = buffer;
|
||||
return ptr->size;
|
||||
}
|
||||
|
||||
@@ -127,5 +127,6 @@ void v9fs_transport_destroy(FAR struct v9fs_transport_s *transport);
|
||||
void v9fs_transport_done(FAR struct v9fs_payload_s *cookie, int ret);
|
||||
int v9fs_fid_put(FAR struct v9fs_client_s *client, uint32_t fid);
|
||||
int v9fs_fid_get(FAR struct v9fs_client_s *client, uint32_t fid);
|
||||
ssize_t v9fs_parse_size(FAR const void *buffer);
|
||||
|
||||
#endif /* __FS_V9FS_CLIENT_H */
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/****************************************************************************
|
||||
* fs/v9fs/socket_9p.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "client.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define V9FS_HEADER_OFFSET 7
|
||||
#define V9FS_DEAFULT_PORT ":563"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct socket_9p_priv_s
|
||||
{
|
||||
struct v9fs_transport_s transport;
|
||||
struct socket psock;
|
||||
mutex_t lock;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int socket_9p_create(FAR struct v9fs_transport_s **transport,
|
||||
FAR const char *args);
|
||||
static int socket_9p_request(FAR struct v9fs_transport_s *transport,
|
||||
FAR struct v9fs_payload_s *payload);
|
||||
static void socket_9p_destroy(FAR struct v9fs_transport_s *transport);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct v9fs_transport_ops_s g_socket_9p_transport_ops =
|
||||
{
|
||||
socket_9p_create, /* create */
|
||||
socket_9p_request, /* request */
|
||||
socket_9p_destroy, /* close */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: socket_9p_create
|
||||
****************************************************************************/
|
||||
|
||||
static int socket_9p_create(FAR struct v9fs_transport_s **transport,
|
||||
FAR const char *args)
|
||||
{
|
||||
FAR struct socket_9p_priv_s *priv;
|
||||
struct sockaddr_in sin;
|
||||
FAR const char *port;
|
||||
FAR const char *addr;
|
||||
int ret;
|
||||
|
||||
/* Parse IP and port */
|
||||
|
||||
addr = strstr(args, "tag=");
|
||||
if (addr == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr += 4;
|
||||
port = strchr(addr, ':');
|
||||
if (port == NULL)
|
||||
{
|
||||
/* set default port */
|
||||
|
||||
port = V9FS_DEAFULT_PORT;
|
||||
}
|
||||
|
||||
priv = kmm_zalloc(sizeof(struct socket_9p_priv_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = psock_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP, &priv->psock);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sin.sin_family = PF_INET;
|
||||
sin.sin_port = htons(atoi(port + 1));
|
||||
sin.sin_addr.s_addr = inet_addr(addr);
|
||||
ret = psock_connect(&priv->psock, (FAR const struct sockaddr *)&sin,
|
||||
sizeof(sin));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
nxmutex_init(&priv->lock);
|
||||
priv->transport.ops = &g_socket_9p_transport_ops;
|
||||
*transport = &priv->transport;
|
||||
return 0;
|
||||
|
||||
out:
|
||||
psock_close(&priv->psock);
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: socket_9p_request
|
||||
****************************************************************************/
|
||||
|
||||
static int socket_9p_request(FAR struct v9fs_transport_s *transport,
|
||||
FAR struct v9fs_payload_s *payload)
|
||||
{
|
||||
FAR struct socket_9p_priv_s *priv =
|
||||
(FAR struct socket_9p_priv_s *)transport;
|
||||
struct msghdr msg;
|
||||
FAR char *ptr;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
memset(&msg, 0, sizeof(struct msghdr));
|
||||
msg.msg_iov = payload->wiov;
|
||||
msg.msg_iovlen = payload->wcount;
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
ret = psock_sendmsg(&priv->psock, &msg, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
ptr = payload->riov[0].iov_base;
|
||||
ret = psock_recvfrom(&priv->psock, ptr, V9FS_HEADER_OFFSET,
|
||||
MSG_WAITALL, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = v9fs_parse_size(ptr);
|
||||
len -= ret;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
/* There is still data left to process */
|
||||
|
||||
int index;
|
||||
|
||||
/* Skip the header */
|
||||
|
||||
payload->riov[0].iov_base += V9FS_HEADER_OFFSET;
|
||||
payload->riov[0].iov_len -= V9FS_HEADER_OFFSET;
|
||||
|
||||
for (index = 0; index < payload->rcount; index++)
|
||||
{
|
||||
payload->riov[index].iov_len =
|
||||
MIN(len, payload->riov[index].iov_len);
|
||||
len -= payload->riov[index].iov_len;
|
||||
}
|
||||
|
||||
msg.msg_iov = payload->riov;
|
||||
msg.msg_iovlen = payload->rcount;
|
||||
|
||||
ret = psock_recvmsg(&priv->psock, &msg, MSG_WAITALL);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Restore the header */
|
||||
|
||||
payload->riov[0].iov_base -= V9FS_HEADER_OFFSET;
|
||||
payload->riov[0].iov_len += V9FS_HEADER_OFFSET;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
nxmutex_unlock(&priv->lock);
|
||||
v9fs_transport_done(payload, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: socket_9p_destroy
|
||||
****************************************************************************/
|
||||
|
||||
static void socket_9p_destroy(FAR struct v9fs_transport_s *transport)
|
||||
{
|
||||
FAR struct socket_9p_priv_s *priv =
|
||||
(FAR struct socket_9p_priv_s *)transport;
|
||||
|
||||
psock_close(&priv->psock);
|
||||
nxmutex_destroy(&priv->lock);
|
||||
kmm_free(priv);
|
||||
}
|
||||
@@ -45,11 +45,17 @@ struct v9fs_transport_ops_map_s
|
||||
#ifdef CONFIG_V9FS_VIRTIO_9P
|
||||
extern const struct v9fs_transport_ops_s g_virtio_9p_transport_ops;
|
||||
#endif
|
||||
#ifdef CONFIG_V9FS_SOCKET_9P
|
||||
extern const struct v9fs_transport_ops_s g_socket_9p_transport_ops;
|
||||
#endif
|
||||
|
||||
static const struct v9fs_transport_ops_map_s g_transport_ops_map[] =
|
||||
{
|
||||
#ifdef CONFIG_V9FS_VIRTIO_9P
|
||||
{ "virtio", &g_virtio_9p_transport_ops },
|
||||
#endif
|
||||
#ifdef CONFIG_V9FS_SOCKET_9P
|
||||
{ "socket", &g_socket_9p_transport_ops },
|
||||
#endif
|
||||
{ NULL, NULL},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user