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:
chenrun1
2024-09-24 18:27:13 +08:00
committed by Xiang Xiao
parent 5f77da4c51
commit 4d17c353dd
7 changed files with 259 additions and 0 deletions
+4
View File
@@ -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()
+5
View File
@@ -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
+4
View File
@@ -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
+10
View File
@@ -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;
}
+1
View File
@@ -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 */
+229
View File
@@ -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);
}
+6
View File
@@ -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},
};