This comment converts the underlying IPC used by the UserFS from Unix domain local sockets to UDP LocalHost loopback sockets. The problem with the local sockets is that they do require operations on the top level psuedo-file system inode tree. That tree must be locked during certain traversals such as enumerate mountpoints or enumerating directory entries.
This conversion is unfortunate in the sense that Unix local domain sockets are relatively lightweight. LocalHost UDP sockets are much heavier weight since they rely on the full UDP stack. If anyone is up for a complete redesign, then using some shared memory and a POSIX message queue would be lightweight again. This commit also fixes several bugs that were not testable before the inode tree deadlock. I cannot say that the logic is 100% stable but it does not have basic functionality. Squashed commit of the following: fs/userfs: Order locking so that access to the shared I/O buffer is also locked. fs/userfs: Converts to use LocalHost UDP loopback for IPC.
This commit is contained in:
parent
2fc5237854
commit
7deb24484c
32
TODO
32
TODO
@ -23,7 +23,7 @@ nuttx/:
|
||||
(4) USB (drivers/usbdev, drivers/usbhost)
|
||||
(0) Other drivers (drivers/)
|
||||
(12) Libraries (libc/, libm/)
|
||||
(11) File system/Generic drivers (fs/, drivers/)
|
||||
(10) File system/Generic drivers (fs/, drivers/)
|
||||
(9) Graphics Subsystem (graphics/)
|
||||
(3) Build system / Toolchains
|
||||
(3) Linux/Cywgin simulation (arch/sim)
|
||||
@ -1963,36 +1963,6 @@ o File system / Generic drivers (fs/, drivers/)
|
||||
ignored by readder() logic. This the file does not
|
||||
appear in the 'ls'.
|
||||
|
||||
Title: DEADLOCKS WITH USERFS
|
||||
Description: UserFS support has been added to NuttX. However, the current
|
||||
version is not very usable due to problems with deadlocks. These
|
||||
deadlocks occur because: (1) logic on the NSH thread locks the
|
||||
inode tree to prevent modification while travering file system
|
||||
entities, but (2) Logic in the UserFS daemon also needs to lock
|
||||
the inode tree. This leads to the deadlock because the logic on
|
||||
the NSH thread cannot unlock the inode tree until the traversal
|
||||
completes but the logic on the UserFS daemon thread is blocked
|
||||
waiting to lock the inodes.
|
||||
|
||||
This can be seen with the NSH mount command which locks the
|
||||
inode tree while traversing all of the mountpoints and also
|
||||
with a simple directory listing with the 'ls' command which
|
||||
locks the inode tree while the directory entries are enumerated.
|
||||
|
||||
The simplest solution would be change the IPC so that it does
|
||||
not interact with the inode tree. The simplest IPC change
|
||||
would be to swith the underlying IPC from Unix domain local
|
||||
sockets to LocalHost loopback sockets. This would add
|
||||
overhead of supporting a UDP stack in all configurations.
|
||||
Another option would be to use shared memory or, perhaps
|
||||
better, shared memory with a message queue.
|
||||
|
||||
Support UserFS is currently marked EXPERIMENTAL to prevent
|
||||
accidentlly enabling the feature.
|
||||
Status: Open
|
||||
Priority: Since this is a new feature, the priority must be low (unless,
|
||||
of course, someone is in dire need of the feature).
|
||||
|
||||
o Graphics Subsystem (graphics/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CONFIG_NET_ETHERNET is not set
|
||||
# CONFIG_NET_IPv4 is not set
|
||||
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||
# CONFIG_NSH_DISABLE_DATE is not set
|
||||
# CONFIG_NSH_NETINIT is not set
|
||||
CONFIG_ARCH_BOARD_SIM=y
|
||||
CONFIG_ARCH_BOARD="sim"
|
||||
CONFIG_ARCH_SIM=y
|
||||
@ -31,7 +31,10 @@ CONFIG_IDLETHREAD_STACKSIZE=4096
|
||||
CONFIG_LIBC_EXECFUNCS=y
|
||||
CONFIG_MAX_TASKS=64
|
||||
CONFIG_NET_LOCAL=y
|
||||
CONFIG_NET_LOOPBACK=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_NFILE_DESCRIPTORS=32
|
||||
CONFIG_NSH_ARCHINIT=y
|
||||
CONFIG_NSH_ARCHROMFS=y
|
||||
@ -46,6 +49,7 @@ CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
|
||||
CONFIG_PTHREAD_STACK_DEFAULT=8192
|
||||
CONFIG_READLINE_TABCOMPLETION=y
|
||||
CONFIG_SCHED_HAVE_PARENT=y
|
||||
CONFIG_SCHED_LPWORK=y
|
||||
CONFIG_SCHED_ONEXIT=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SDCLONE_DISABLE=y
|
||||
|
@ -14,26 +14,6 @@ config NETDEV_LOOPBACK
|
||||
Add support for the local network loopback device, lo.
|
||||
|
||||
if NETDEV_LOOPBACK
|
||||
|
||||
choice
|
||||
prompt "Work queue"
|
||||
default LOOPBACK_LPWORK if SCHED_LPWORK
|
||||
default LOOPBACK_HPWORK if !SCHED_LPWORK && SCHED_HPWORK
|
||||
depends on SCHED_WORKQUEUE
|
||||
---help---
|
||||
Work queue support is required to use the loopback driver. If the
|
||||
low priority work queue is available, then it should be used by the
|
||||
loopback driver.
|
||||
|
||||
config LOOPBACK_HPWORK
|
||||
bool "High priority"
|
||||
depends on SCHED_HPWORK
|
||||
|
||||
config LOOPBACK_LPWORK
|
||||
bool "Low priority"
|
||||
depends on SCHED_LPWORK
|
||||
|
||||
endchoice # Work queue
|
||||
endif # NETDEV_LOOPBACK
|
||||
|
||||
config NETDEV_TELNET
|
||||
|
@ -38,7 +38,6 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#if defined(CONFIG_NET) && defined(CONFIG_NETDEV_LOOPBACK)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@ -63,6 +62,8 @@
|
||||
# include <nuttx/net/pkt.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETDEV_LOOPBACK
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -71,14 +72,6 @@
|
||||
|
||||
#if !defined(CONFIG_SCHED_WORKQUEUE)
|
||||
# error Worker thread support is required (CONFIG_SCHED_WORKQUEUE)
|
||||
#else
|
||||
# if defined(CONFIG_LOOPBACK_HPWORK)
|
||||
# define LPBKWORK HPWORK
|
||||
# elif defined(CONFIG_LOOPBACK_LPWORK)
|
||||
# define LPBKWORK LPWORK
|
||||
# else
|
||||
# error Neither CONFIG_LOOPBACK_HPWORK nor CONFIG_LOOPBACK_LPWORK defined
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
|
||||
@ -283,7 +276,7 @@ static void lo_poll_expiry(int argc, wdparm_t arg, ...)
|
||||
|
||||
/* Schedule to perform the interrupt processing on the worker thread. */
|
||||
|
||||
work_queue(LPBKWORK, &priv->lo_work, lo_poll_work, priv, 0);
|
||||
work_queue(LPWORK, &priv->lo_work, lo_poll_work, priv, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -429,7 +422,7 @@ static int lo_txavail(FAR struct net_driver_s *dev)
|
||||
{
|
||||
/* Schedule to serialize the poll on the worker thread. */
|
||||
|
||||
work_queue(LPBKWORK, &priv->lo_work, lo_txavail_work, priv, 0);
|
||||
work_queue(LPWORK, &priv->lo_work, lo_txavail_work, priv, 0);
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -558,4 +551,4 @@ int localhost_initialize(void)
|
||||
return lo_ifup(&priv->lo_dev);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NETDEV_LOOPBACK */
|
||||
#endif /* CONFIG_NETDEV_LOOPBACK */
|
||||
|
@ -6,7 +6,7 @@
|
||||
config FS_USERFS
|
||||
bool "User file system"
|
||||
default n
|
||||
depends on NET_LOCAL && EXPERIMENTAL
|
||||
depends on NET_IPv4 && NET_UDP && NETDEV_LOOPBACK
|
||||
---help---
|
||||
Enable support for user file system. See include/nuttx/fs/userfs.h
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,10 +55,9 @@
|
||||
* 1. The UserFS OS support will be instantiated when the UserFS is mounted
|
||||
* based upon the configuration passed in the optional data of the
|
||||
* mount command.
|
||||
* 2. The UserFS instance N will be configured to communicate on a Unix
|
||||
* domain local socket with address: /dev/userfsN where N is the same
|
||||
* value as was when file system was created. The Unix domain socket
|
||||
* handles both client to server requests and server-to-client responses.
|
||||
* 2. The UserFS server port number will be configured to communicate on a
|
||||
* LocalHost UDP socket with the server portof 0x83nn where nn is the
|
||||
* value that was provided when file system was created.
|
||||
* 3. The UserFs will receive system file system requests and forward them
|
||||
* on the the MqUfsReqN to the user-space file system server
|
||||
* (userfs_run()). These requests may be accompanied by additional data in
|
||||
@ -66,12 +65,12 @@
|
||||
* created. This buffer would hold, for example, the data to be
|
||||
* written that would accompany a write request.
|
||||
* 4. The user-space logic of userfs_run() listens at the other end of the
|
||||
* Unix domain socket. It will receive the requests and forward them
|
||||
* LocalHost socket. It will receive the requests and forward them
|
||||
* to the user file system implementation via the methods of struct
|
||||
* userfs_operations_s
|
||||
* 5. Responses generated by the struct userfs_operations_s method will be
|
||||
* returned to UserFS via the Unix domain socket.
|
||||
* 6. The UserFS kernel thread will listen on the Unix local domain socket
|
||||
* returned to UserFS via the LocalHost socket.
|
||||
* 6. The UserFS kernel thread will listen on the LocalHost socket
|
||||
* and will receive the user file system responses and forward them to
|
||||
* the kernel-space file system client.
|
||||
*/
|
||||
@ -104,19 +103,17 @@
|
||||
* Input: This function receives an pointer to a read-only instance of
|
||||
* struct userfs_config_s that contains information needed to
|
||||
* configure the UserFS instance.
|
||||
* Output: On success the UserFS N instance is created. N is non-negative
|
||||
* Output: On success the UserFS nn instance is created. nn is non-negative
|
||||
* and will be provided as the IOCTL return value on success. On
|
||||
* failure, ioctl() will return -1 with the errno variable set to
|
||||
* indicate the cause of the failure.
|
||||
*/
|
||||
|
||||
/* Format statements that should be used in creating Unix domain addresses */
|
||||
/* This is the base value of the server port number. The actual range is
|
||||
* 0x8300 through 0x83ff.
|
||||
*/
|
||||
|
||||
#define USERFS_SERVER_FMT "/dev/userver%u"
|
||||
#define USERFS_SERVER_MAXLEN (18)
|
||||
|
||||
#define USERFS_CLIENT_FMT "/dev/uclient%u"
|
||||
#define USERFS_CLIENT_MAXLEN (18)
|
||||
#define USERFS_SERVER_PORTBASE 0x8300
|
||||
|
||||
/* It looks like the maximum size of a request is 16 bytes. We will allow a
|
||||
* little more for the maximum size of a request structure.
|
||||
@ -194,7 +191,7 @@ enum userfs_resp_e
|
||||
struct userfs_config_s
|
||||
{
|
||||
size_t mxwrite; /* The max size of a write data */
|
||||
int instance; /* Instance number used to create unique naming */
|
||||
uint16_t portno; /* The server port number (host order) */
|
||||
};
|
||||
|
||||
/* This structure identifies the user-space file system operations. */
|
||||
@ -561,13 +558,13 @@ int userfs_register(void);
|
||||
*
|
||||
* 1. It configures and creates the UserFS file system and
|
||||
* 2. Mounts the user file system at the provide mount point path.
|
||||
* 2. Receives file system requests on the Unix doamin local socket with
|
||||
* address /dev/userfsN where N is the same as above,
|
||||
* 2. Receives file system requests on the LocalHost socket with
|
||||
* server port 0x83nn where nn is the same as above,
|
||||
* 3. Received file system requests are marshaled and dispatch to the
|
||||
* user file system via callbacks to the operations provided by
|
||||
* "userops", and
|
||||
* 3. Returns file system responses generated by the callbacks via the
|
||||
* same Unix domain local socket.
|
||||
* 3. Returns file system responses generated by the callbacks to the
|
||||
* LocalHost client socket.
|
||||
*
|
||||
* NOTE: This is a user function that is implemented as part of the
|
||||
* NuttX C library and is intended to be called by appliation logic.
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -52,20 +51,11 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <nuttx/fs/userfs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definition
|
||||
****************************************************************************/
|
||||
/* There is a bug in the local socket recvfrom() logic as of this writing:
|
||||
* The recvfrom logic for local datagram sockets returns the incorrect
|
||||
* sender "from" address. Instead, it returns the receiver's "to" address.
|
||||
* This means that returning a reply to the "from" address receiver sending
|
||||
* a packet to itself.
|
||||
*/
|
||||
|
||||
#define LOCAL_RECVFROM_WAR 1
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -74,8 +64,7 @@ struct userfs_info_s
|
||||
{
|
||||
FAR const struct userfs_operations_s *userops; /* File system callbacks */
|
||||
FAR void *volinfo; /* Data that accompanies the user callbacks */
|
||||
struct sockaddr_un client; /* Client to send response back to */
|
||||
socklen_t addrlen; /* Length of the client address */
|
||||
struct sockaddr_in client; /* Client to send response back to */
|
||||
int16_t sockfd; /* Server socket */
|
||||
uint16_t iolen; /* Size of I/O buffer */
|
||||
uint16_t mxwrite; /* The max size of a write data */
|
||||
@ -93,18 +82,18 @@ struct userfs_info_s
|
||||
* not generate unique instance numbers.
|
||||
*/
|
||||
|
||||
static sem_t g_userfs_exclsem = SEM_INITIALIZER(1);
|
||||
static uint16_t g_userfs_next_instance;
|
||||
static sem_t g_userfs_exclsem = SEM_INITIALIZER(1);
|
||||
static uint8_t g_userfs_next_instance;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_instance
|
||||
* Name: userfs_server_portno
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint16_t userfs_instance(void)
|
||||
static inline uint16_t userfs_server_portno(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -118,7 +107,7 @@ static inline uint16_t userfs_instance(void)
|
||||
* happen if g_userfs_next_instance were to wrap around.
|
||||
*/
|
||||
|
||||
ret = g_userfs_next_instance++;
|
||||
ret = USERFS_SERVER_PORTBASE | g_userfs_next_instance++;
|
||||
nxsem_post(&g_userfs_exclsem);
|
||||
}
|
||||
|
||||
@ -164,14 +153,16 @@ static inline int userfs_open_dispatch(FAR struct userfs_info_s *info,
|
||||
*/
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->open != NULL);
|
||||
resp.ret = info->userops->open(info->volinfo, req->relpath, req->oflags,
|
||||
req->mode, &resp.openinfo);
|
||||
resp.ret = info->userops->open(info->volinfo, req->relpath, req->oflags,
|
||||
req->mode, &resp.openinfo);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_OPEN;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_open_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_open_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (nsent < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
@ -201,13 +192,15 @@ static inline int userfs_close_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->close != NULL);
|
||||
resp.ret = info->userops->close(info->volinfo, req->openinfo);
|
||||
resp.ret = info->userops->close(info->volinfo, req->openinfo);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_CLOSE;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_close_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_close_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -242,10 +235,11 @@ static inline int userfs_read_dispatch(FAR struct userfs_info_s *info,
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp->resp = USERFS_RESP_READ;
|
||||
resplen = SIZEOF_USERFS_READ_RESPONSE_S(resp->nread);
|
||||
nsent = sendto(info->sockfd, resp, resplen, 0,
|
||||
(FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
resp->resp = USERFS_RESP_READ;
|
||||
resplen = SIZEOF_USERFS_READ_RESPONSE_S(resp->nread);
|
||||
nsent = sendto(info->sockfd, resp, resplen, 0,
|
||||
(FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -284,9 +278,11 @@ static inline int userfs_write_dispatch(FAR struct userfs_info_s *info,
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_WRITE;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_write_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
resp.resp = USERFS_RESP_WRITE;
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_write_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -306,14 +302,16 @@ static inline int userfs_seek_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->seek != NULL);
|
||||
resp.ret = info->userops->seek(info->volinfo, req->openinfo, req->offset,
|
||||
req->whence);
|
||||
resp.ret = info->userops->seek(info->volinfo, req->openinfo, req->offset,
|
||||
req->whence);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_SEEK;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_seek_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_seek_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -333,14 +331,16 @@ static inline int userfs_ioctl_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->ioctl != NULL);
|
||||
resp.ret = info->userops->ioctl(info->volinfo, req->openinfo, req->cmd,
|
||||
req->arg);
|
||||
resp.ret = info->userops->ioctl(info->volinfo, req->openinfo, req->cmd,
|
||||
req->arg);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_IOCTL;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_ioctl_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_ioctl_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -360,13 +360,15 @@ static inline int userfs_sync_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->sync != NULL);
|
||||
resp.ret = info->userops->sync(info->volinfo, req->openinfo);
|
||||
resp.ret = info->userops->sync(info->volinfo, req->openinfo);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_SYNC;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_sync_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_sync_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -386,13 +388,15 @@ static inline int userfs_dup_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->dup != NULL);
|
||||
resp.ret = info->userops->dup(info->volinfo, req->openinfo, &resp.openinfo);
|
||||
resp.ret = info->userops->dup(info->volinfo, req->openinfo, &resp.openinfo);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_DUP;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_dup_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_dup_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -412,13 +416,15 @@ static inline int userfs_fstat_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->fstat != NULL);
|
||||
resp.ret = info->userops->fstat(info->volinfo, req->openinfo, &resp.buf);
|
||||
resp.ret = info->userops->fstat(info->volinfo, req->openinfo, &resp.buf);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_FSTAT;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_fstat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_fstat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -452,13 +458,15 @@ static inline int userfs_opendir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->opendir != NULL);
|
||||
resp.ret = info->userops->opendir(info->volinfo, req->relpath, &resp.dir);
|
||||
resp.ret = info->userops->opendir(info->volinfo, req->relpath, &resp.dir);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_OPENDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_opendir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_opendir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -478,13 +486,15 @@ static inline int userfs_closedir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->closedir != NULL);
|
||||
resp.ret = info->userops->closedir(info->volinfo, req->dir);
|
||||
resp.ret = info->userops->closedir(info->volinfo, req->dir);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_CLOSEDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_open_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_closedir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -504,13 +514,15 @@ static inline int userfs_readdir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->readdir != NULL);
|
||||
resp.ret = info->userops->readdir(info->volinfo, req->dir, &resp.entry);
|
||||
resp.ret = info->userops->readdir(info->volinfo, req->dir, &resp.entry);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_READDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_readdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_readdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -530,13 +542,15 @@ static inline int userfs_rewinddir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->rewinddir != NULL);
|
||||
resp.ret = info->userops->rewinddir(info->volinfo, req->dir);
|
||||
resp.ret = info->userops->rewinddir(info->volinfo, req->dir);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_REWINDDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_rewinddir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_rewinddir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -556,13 +570,15 @@ static inline int userfs_statfs_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->statfs != NULL);
|
||||
resp.ret = info->userops->statfs(info->volinfo, &resp.buf);
|
||||
resp.ret = info->userops->statfs(info->volinfo, &resp.buf);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_STATFS;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_statfs_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_statfs_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -596,13 +612,15 @@ static inline int userfs_unlink_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->unlink != NULL);
|
||||
resp.ret = info->userops->unlink(info->volinfo, req->relpath);
|
||||
resp.ret = info->userops->unlink(info->volinfo, req->relpath);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_UNLINK;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_unlink_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_unlink_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -636,13 +654,15 @@ static inline int userfs_mkdir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->mkdir != NULL);
|
||||
resp.ret = info->userops->mkdir(info->volinfo, req->relpath, req->mode);
|
||||
resp.ret = info->userops->mkdir(info->volinfo, req->relpath, req->mode);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_MKDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_mkdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_mkdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -676,13 +696,15 @@ static inline int userfs_rmdir_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->rmdir != NULL);
|
||||
resp.ret = info->userops->rmdir(info->volinfo, req->relpath);
|
||||
resp.ret = info->userops->rmdir(info->volinfo, req->relpath);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_RMDIR;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_rmdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_rmdir_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -729,14 +751,16 @@ static inline int userfs_rename_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->rename != NULL);
|
||||
resp.ret = info->userops->rename(info->volinfo, req->oldrelpath,
|
||||
newrelpath);
|
||||
resp.ret = info->userops->rename(info->volinfo, req->oldrelpath,
|
||||
newrelpath);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_RENAME;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_rename_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_rename_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -770,13 +794,15 @@ static inline int userfs_stat_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->stat != NULL);
|
||||
resp.ret = info->userops->stat(info->volinfo, req->relpath, &resp.buf);
|
||||
resp.ret = info->userops->stat(info->volinfo, req->relpath, &resp.buf);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_STAT;
|
||||
nsent = sendto(info->sockfd, &resp, sizeof(struct userfs_stat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client, info->addrlen);
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_stat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
@ -796,7 +822,7 @@ static inline int userfs_destroy_dispatch(FAR struct userfs_info_s *info,
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->destroy != NULL);
|
||||
resp.ret = info->userops->destroy(info->volinfo);
|
||||
resp.ret = info->userops->destroy(info->volinfo);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
@ -804,7 +830,7 @@ static inline int userfs_destroy_dispatch(FAR struct userfs_info_s *info,
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_destroy_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
info->addrlen);
|
||||
sizeof(struct sockaddr_in));
|
||||
if (nsent < 0)
|
||||
{
|
||||
int ret = -errno;
|
||||
@ -836,13 +862,13 @@ static inline int userfs_destroy_dispatch(FAR struct userfs_info_s *info,
|
||||
*
|
||||
* 1. It configures and creates the UserFS file system and
|
||||
* 2. Mounts the user file system at the provide mount point path.
|
||||
* 2. Receives file system requests on the Unix doamin local socket with
|
||||
* address /dev/userfsN where N is the same as above,
|
||||
* 2. Receives file system requests on the LocalHost socket with
|
||||
* server port 0x83nn where nn is the same as above,
|
||||
* 3. Received file system requests are marshaled and dispatch to the
|
||||
* user file system via callbacks to the operations provided by
|
||||
* "userops", and
|
||||
* 3. Returns file system responses generated by the callbacks via the
|
||||
* same Unix domain local socket.
|
||||
* 3. Returns file system responses generated by the callbacks to the
|
||||
* LocalHost client socket.
|
||||
*
|
||||
* NOTE: This is a user function that is implemented as part of the
|
||||
* NuttX C library and is intended to be called by appliation logic.
|
||||
@ -869,7 +895,7 @@ int userfs_run(FAR const char *mountpt,
|
||||
{
|
||||
FAR struct userfs_info_s *info;
|
||||
FAR struct userfs_config_s config;
|
||||
struct sockaddr_un server;
|
||||
struct sockaddr_in server;
|
||||
unsigned int iolen;
|
||||
socklen_t addrlen;
|
||||
ssize_t nread;
|
||||
@ -878,7 +904,7 @@ int userfs_run(FAR const char *mountpt,
|
||||
DEBUGASSERT(mountpt != NULL && userops != NULL && mxwrite <= UINT16_MAX);
|
||||
DEBUGASSERT(mxwrite > 0 && mxwrite <= (UINT16_MAX - USERFS_REQ_MAXSIZE));
|
||||
|
||||
/* Allocate a state structrue with an I/O buffer to receive UserFS requests */
|
||||
/* Allocate a state structure with an I/O buffer to receive UserFS requests */
|
||||
|
||||
iolen = USERFS_REQ_MAXSIZE + mxwrite;
|
||||
info = (FAR struct userfs_info_s *)zalloc(SIZEOF_USERFS_INFO_S(iolen));
|
||||
@ -900,7 +926,7 @@ int userfs_run(FAR const char *mountpt,
|
||||
*/
|
||||
|
||||
config.mxwrite = mxwrite;
|
||||
config.instance = userfs_instance();
|
||||
config.portno = userfs_server_portno();
|
||||
|
||||
/* Mounts the user file system at the provided mount point path. */
|
||||
|
||||
@ -912,9 +938,9 @@ int userfs_run(FAR const char *mountpt,
|
||||
goto errout_with_info;
|
||||
}
|
||||
|
||||
/* Create a new Unix domain datagram server socket */
|
||||
/* Create a new LocalHost UDP server socket */
|
||||
|
||||
info->sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
|
||||
info->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (info->sockfd < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
@ -922,15 +948,14 @@ int userfs_run(FAR const char *mountpt,
|
||||
goto errout_with_info;
|
||||
}
|
||||
|
||||
/* Bind the socket to a local server address */
|
||||
/* Bind the socket to a server port number */
|
||||
|
||||
server.sun_family = AF_LOCAL;
|
||||
snprintf(server.sun_path, UNIX_PATH_MAX, USERFS_SERVER_FMT,
|
||||
config.instance);
|
||||
server.sun_path[UNIX_PATH_MAX - 1] = '\0';
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(config.portno);
|
||||
server.sin_addr.s_addr = HTONL(INADDR_LOOPBACK);
|
||||
|
||||
addrlen = strlen(server.sun_path) + sizeof(sa_family_t) + 1;
|
||||
ret = bind(info->sockfd, (struct sockaddr*)&server, addrlen);
|
||||
ret = bind(info->sockfd, (struct sockaddr *)&server,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
@ -938,19 +963,6 @@ int userfs_run(FAR const char *mountpt,
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
#ifdef LOCAL_RECVFROM_WAR
|
||||
/* Since this is a simple point-to-point communication with well known
|
||||
* addresses at each endpoint, we can preset the client address.
|
||||
*/
|
||||
|
||||
info->client.sun_family = AF_LOCAL;
|
||||
snprintf(info->client.sun_path, UNIX_PATH_MAX, USERFS_CLIENT_FMT,
|
||||
config.instance);
|
||||
info->client.sun_path[UNIX_PATH_MAX - 1] = '\0';
|
||||
|
||||
info->addrlen = strlen(info->client.sun_path) + sizeof(sa_family_t) + 1;
|
||||
#endif
|
||||
|
||||
/* Receive file system requests on the POSIX message queue as long
|
||||
* as the mount persists.
|
||||
*/
|
||||
@ -960,16 +972,10 @@ int userfs_run(FAR const char *mountpt,
|
||||
/* Receive the next file system request */
|
||||
|
||||
finfo("Receiving up %u bytes\n", info->iolen);
|
||||
#ifdef LOCAL_RECVFROM_WAR
|
||||
nread = recvfrom(info->sockfd, info->iobuffer, info->iolen, 0,
|
||||
NULL, NULL);
|
||||
#else
|
||||
info->addrlen = 0;
|
||||
nread = recvfrom(info->sockfd, info->iobuffer, info->iolen, 0,
|
||||
(FAR struct sockaddr *)&info->client,
|
||||
&info->addrlen);
|
||||
#endif
|
||||
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
nread = recvfrom(info->sockfd, info->iobuffer, info->iolen, 0,
|
||||
(FAR struct sockaddr *)&info->client,
|
||||
&addrlen);
|
||||
if (nread < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
@ -977,10 +983,7 @@ int userfs_run(FAR const char *mountpt,
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
#ifndef LOCAL_RECVFROM_WAR
|
||||
DEBUGASSERT(info->addrlen >= sizeof(sa_family_t) &&
|
||||
info->addrlen <= sizeof(struct sockaddr_un));
|
||||
#endif
|
||||
DEBUGASSERT(addrlen == sizeof(struct sockaddr_in));
|
||||
|
||||
/* Process the request according to its request ID */
|
||||
|
||||
@ -1095,7 +1098,7 @@ int userfs_run(FAR const char *mountpt,
|
||||
}
|
||||
while (ret == OK);
|
||||
|
||||
/* Close the Unix domain socket */
|
||||
/* Close the LocalHost socket */
|
||||
|
||||
errout_with_sockfd:
|
||||
close(info->sockfd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user