scoutfs: remove unused client and server code

The previous commit added shared networking code and disabled the old
unused code.  This removes all that unused client and server code that
was refactored to become the shared networking code.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-07-27 09:50:21 -07:00
committed by Zach Brown
parent 17dec65a52
commit d708421cfb
5 changed files with 1 additions and 808 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include
scoutfs-y += bio.o block.o btree.o client.o compact.o counters.o data.o dir.o \
export.o extents.o file.o inode.o ioctl.o item.o lock.o \
manifest.o msg.o net.o options.o per_task.o seg.o server.o \
scoutfs_trace.o sock.o sort_priv.o super.o sysfs.o trans.o \
scoutfs_trace.o sort_priv.o super.o sysfs.o trans.o \
triggers.o xattr.o
#
-446
View File
@@ -30,7 +30,6 @@
#include "compact.h"
#include "scoutfs_trace.h"
#include "msg.h"
#include "server.h"
#include "client.h"
#include "net.h"
#include "endian_swap.h"
@@ -40,22 +39,6 @@
* super to get the address it should try and connect to.
*/
#define SIN_FMT "%pIS:%u"
#define SIN_ARG(sin) sin, be16_to_cpu((sin)->sin_port)
#if 0
/*
* Have a pretty aggressive keepalive timeout of around 10 seconds. The
* TCP keepalives are being processed out of task context so they should
* be responsive even when mounts are under load. We also derive the
* connect timeout from this.
*/
#define KEEPCNT 3
#define KEEPIDLE 7
#define KEEPINTVL 1
#endif
/*
* Connection timeouts have to allow for enough time for servers to
* reboot. Figure order minutes at the outside.
@@ -77,126 +60,6 @@ struct client_info {
unsigned long conn_retry_ms;
};
#if 0
struct waiting_sender {
struct rb_node node;
struct task_struct *task;
u64 id;
void *rx;
size_t rx_size;
int result;
};
static struct waiting_sender *walk_sender_tree(struct client_info *client,
u64 id,
struct waiting_sender *ins)
{
struct rb_node **node = &client->sender_root.rb_node;
struct waiting_sender *found = NULL;
struct waiting_sender *sender;
struct rb_node *parent = NULL;
assert_spin_locked(&client->recv_lock);
while (*node) {
parent = *node;
sender = container_of(*node, struct waiting_sender, node);
if (id < sender->id) {
node = &(*node)->rb_left;
} else if (id > sender->id) {
node = &(*node)->rb_right;
} else {
found = sender;
break;
}
}
if (ins) {
/* ids are never reused and assigned under lock */
BUG_ON(found);
rb_link_node(&ins->node, parent, node);
rb_insert_color(&ins->node, &client->sender_root);
found = ins;
}
return found;
}
/*
* This work is queued once the socket is created. It blocks trying to
* receive replies to sent messages. If the sender is still around it
* receives the reply data into their buffer. If the sender has left
* then it silently drops the reply.
*
* This exits once someone shuts down the socket. If this sees a fatal
* error it shuts down the socket which causes senders to reconnect.
*/
static void scoutfs_client_recv_func(struct work_struct *work)
{
struct client_info *client = container_of(work, struct client_info,
recv_work);
struct waiting_sender *sender;
struct scoutfs_net_header nh;
void *rx = NULL;
u16 data_len;
int ret;
for (;;) {
/* receive the header */
ret = scoutfs_sock_recvmsg(client->sock, &nh, sizeof(nh));
if (ret)
break;
data_len = le16_to_cpu(nh.data_len);
trace_scoutfs_client_recv_reply(client->sb,
&client->sockname,
&client->peername, &nh);
/* receive the payload */
kfree(rx);
rx = kmalloc(data_len, GFP_NOFS);
if (!rx) {
ret = -ENOMEM;
break;
}
/* recv failure can be server crashing, not fatal */
ret = scoutfs_sock_recvmsg(client->sock, rx, data_len);
if (ret) {
break;
}
/* give the payload to a sender if there is one */
spin_lock(&client->recv_lock);
sender = walk_sender_tree(client, le64_to_cpu(nh.id), NULL);
if (sender) {
/* protocol mismatch is fatal */
if (sender->rx_size < data_len) {
sender->result = -EIO;
} else {
memcpy(sender->rx, rx, data_len);
sender->result = 0;
}
smp_mb(); /* store result before waking */
wake_up_process(sender->task);
}
spin_unlock(&client->recv_lock);
}
/* make senders reconnect if we see an rx error */
if (ret) {
/* XXX would need to break out send */
kernel_sock_shutdown(client->sock, SHUT_RDWR);
client->recv_shutdown = true;
}
kfree(rx);
}
#endif
static void reset_connect_timeout(struct client_info *client)
{
client->conn_retry_ms = CONN_RETRY_MIN_MS;
@@ -208,315 +71,6 @@ static void grow_connect_timeout(struct client_info *client)
CONN_RETRY_MAX_MS);
}
#if 0
/*
* Clients who try to send and don't see a connected socket call here to
* connect to the server. They get the server address and try to
* connect.
*
* Each sending client will always try to connect once. After that
* it'll sleep and retry connecting at increasing intervals. After long
* enough it will return an error. Future attempts will retry once then
* return errors.
*/
static int client_connect(struct client_info *client)
{
struct super_block *sb = client->sb;
struct scoutfs_super_block super;
struct scoutfs_net_greeting greet;
struct sockaddr_in *sin;
struct socket *sock = NULL;
struct timeval tv;
struct kvec kv;
int retries;
int addrlen;
int optval;
int ret;
BUG_ON(!mutex_is_locked(&client->send_mutex));
for(retries = 0; ; retries++) {
if (sock) {
sock_release(sock);
sock = NULL;
}
if (retries) {
/* we tried, and we're past limit, return error */
if (time_after(jiffies, client->conn_retry_limit_j)) {
ret = -ENOTCONN;
break;
}
msleep_interruptible(client->conn_retry_ms);
client->conn_retry_ms = min(client->conn_retry_ms * 2,
CONN_RETRY_MAX_MS);
}
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
ret = scoutfs_read_super(sb, &super);
if (ret)
continue;
if (super.server_addr.addr == cpu_to_le32(INADDR_ANY))
continue;
sin = &client->peername;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = le32_to_be32(super.server_addr.addr);
sin->sin_port = le16_to_be16(super.server_addr.port);
ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP,
&sock);
if (ret)
continue;
optval = 1;
ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(char *)&optval, sizeof(optval));
if (ret)
continue;
/* use short timeout for connect itself */
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
(char *)&tv, sizeof(tv));
if (ret)
continue;
client->sock = sock;
ret = kernel_connect(sock, (struct sockaddr *)sin,
sizeof(struct sockaddr_in), 0);
if (ret)
continue;
greet.fsid = super.id;
greet.format_hash = super.format_hash;
kv.iov_base = &greet;
kv.iov_len = sizeof(greet);
ret = scoutfs_sock_sendmsg(sock, &kv, 1);
if (ret)
continue;
ret = scoutfs_sock_recvmsg(sock, &greet, sizeof(greet));
if (ret)
continue;
if (greet.fsid != super.id) {
scoutfs_warn(sb, "server "SIN_FMT" has fsid 0x%llx, expected 0x%llx",
SIN_ARG(&client->peername),
le64_to_cpu(greet.fsid),
le64_to_cpu(super.id));
continue;
}
if (greet.format_hash != super.format_hash) {
scoutfs_warn(sb, "server "SIN_FMT" has format hash 0x%llx, expected 0x%llx",
SIN_ARG(&client->peername),
le64_to_cpu(greet.format_hash),
le64_to_cpu(super.format_hash));
continue;
}
/* but use a keepalive timeout instead of send timeout */
tv.tv_sec = 0;
tv.tv_usec = 0;
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
(char *)&tv, sizeof(tv));
if (ret)
continue;
optval = KEEPCNT;
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
(char *)&optval, sizeof(optval));
if (ret)
continue;
optval = KEEPIDLE;
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
(char *)&optval, sizeof(optval));
if (ret)
continue;
optval = KEEPINTVL;
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
(char *)&optval, sizeof(optval));
if (ret)
continue;
optval = 1;
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(char *)&optval, sizeof(optval));
if (ret)
continue;
addrlen = sizeof(struct sockaddr_in);
ret = kernel_getsockname(sock,
(struct sockaddr *)&client->sockname,
&addrlen);
if (ret)
continue;
scoutfs_info(sb, "client connected "SIN_FMT" -> "SIN_FMT,
SIN_ARG(&client->sockname),
SIN_ARG(&client->peername));
client->sock_gen++;
client->recv_shutdown = false;
reset_connect_timeouts(client);
queue_work(client->recv_wq, &client->recv_work);
wake_up(&client->waitq);
ret = 0;
break;
}
if (ret && sock)
sock_release(sock);
return ret;
}
/* either a sender or unmount is destroying the socket */
static void shutdown_sock_sync(struct client_info *client)
{
struct super_block *sb = client->sb;
struct socket *sock = client->sock;
if (sock) {
kernel_sock_shutdown(sock, SHUT_RDWR);
cancel_work_sync(&client->recv_work);
sock_release(sock);
client->sock = NULL;
scoutfs_info(sb, "client disconnected "SIN_FMT" -> "SIN_FMT,
SIN_ARG(&client->sockname),
SIN_ARG(&client->peername));
}
}
/*
* Senders sleep waiting for a reply to come down the connection out
* which they just sent a request. They need to wake up when the recv
* work has given them a reply or when it's given up and the sender
* needs to reconnect and resend.
*
* This is a condition for wait_event. The barrier orders the task
* state store before loading the sender and client fields.
*/
static int sender_should_wake(struct client_info *client,
struct waiting_sender *sender)
{
smp_mb();
return sender->result != -EINPROGRESS || client->recv_shutdown;
}
/*
* Block sending a request and then waiting for the reply. All senders
* are responsible for connecting sockets and sending their requests.
* recv work blocks receiving from the socket and waking senders if
* they're reply has been copied to their buffer. If the socket sees an
* error the recv work will shutdown and wake us to reconnect.
*/
static int client_request(struct client_info *client, int type, void *data,
unsigned data_len, void *rx, size_t rx_size)
{
struct waiting_sender sender;
struct scoutfs_net_header nh;
struct kvec kv[2];
unsigned kv_len;
u64 sent_to_gen = ~0ULL;
int ret = 0;
if (WARN_ON_ONCE(!data && data_len))
return -EINVAL;
spin_lock(&client->recv_lock);
sender.task = current;
sender.id = client->next_id++;
sender.rx = rx;
sender.rx_size = rx_size;
sender.result = -EINPROGRESS;
nh.id = cpu_to_le64(sender.id);
nh.data_len = cpu_to_le16(data_len);
nh.type = type;
nh.status = SCOUTFS_NET_STATUS_REQUEST;
walk_sender_tree(client, sender.id, &sender);
spin_unlock(&client->recv_lock);
mutex_lock(&client->send_mutex);
while (sender.result == -EINPROGRESS) {
if (!client->sock) {
ret = client_connect(client);
if (ret < 0)
break;
}
if (sent_to_gen != client->sock_gen) {
kv[0].iov_base = &nh;
kv[0].iov_len = sizeof(nh);
kv[1].iov_base = data;
kv[1].iov_len = data_len;
kv_len = data ? 2 : 1;
trace_scoutfs_client_send_request(client->sb,
&client->sockname,
&client->peername,
&nh);
ret = scoutfs_sock_sendmsg(client->sock, kv, kv_len);
if (ret) {
shutdown_sock_sync(client);
continue;
}
sent_to_gen = client->sock_gen;
}
mutex_unlock(&client->send_mutex);
ret = wait_event_interruptible(client->waitq,
sender_should_wake(client, &sender));
if (ret < 0 && sender.result == -EINPROGRESS) {
sender.result = ret;
ret = 0;
}
mutex_lock(&client->send_mutex);
/* finish tearing down the socket if recv shutdown */
if (client->sock && client->recv_shutdown) {
shutdown_sock_sync(client);
continue;
}
}
mutex_unlock(&client->send_mutex);
/* only we remove senders, recv only uses senders under the lock */
spin_lock(&client->recv_lock);
rb_erase(&sender.node, &client->sender_root);
spin_unlock(&client->recv_lock);
if (ret == 0)
ret = sender.result;
return ret;
}
#endif
/*
* Ask for a new run of allocated inode numbers. The server can return
* fewer than @count. It will success with nr == 0 if we've run out.
-258
View File
@@ -30,7 +30,6 @@
#include "compact.h"
#include "scoutfs_trace.h"
#include "msg.h"
#include "client.h"
#include "server.h"
#include "net.h"
#include "endian_swap.h"
@@ -46,9 +45,6 @@
* mount will have less trouble.
*/
#define SIN_FMT "%pIS:%u"
#define SIN_ARG(sin) sin, be16_to_cpu((sin)->sin_port)
struct server_info {
struct super_block *sb;
@@ -81,26 +77,6 @@ struct server_info {
#define DECLARE_SERVER_INFO(sb, name) \
struct server_info *name = SCOUTFS_SB(sb)->server_info
#if 0
struct server_request {
struct server_connection *conn;
struct work_struct work;
struct scoutfs_net_header nh;
/* data payload is allocated here, referenced as ->nh.data */
};
struct server_connection {
struct server_info *server;
struct sockaddr_in sockname;
struct sockaddr_in peername;
struct list_head head;
struct socket *sock;
struct work_struct recv_work;
struct mutex send_mutex;
};
#endif
struct commit_waiter {
struct completion comp;
struct llist_node node;
@@ -585,57 +561,6 @@ out:
trace_scoutfs_server_commit_work_exit(sb, 0, ret);
}
#if 0
/*
* Request processing synchronously sends their reply from within their
* processing work. If this fails the socket is shutdown.
*/
static int send_reply(struct server_connection *conn, u64 id,
u8 type, int error, void *data, unsigned data_len)
{
struct scoutfs_net_header nh;
struct kvec kv[2];
unsigned kv_len;
u8 status;
int ret;
if (WARN_ON_ONCE(error > 0) || WARN_ON_ONCE(data && data_len == 0))
return -EINVAL;
kv[0].iov_base = &nh;
kv[0].iov_len = sizeof(nh);
kv_len = 1;
/* maybe we can have better error communication to clients */
if (error < 0) {
status = SCOUTFS_NET_STATUS_ERROR;
data = NULL;
data_len = 0;
} else {
status = SCOUTFS_NET_STATUS_SUCCESS;
if (data) {
kv[1].iov_base = data;
kv[1].iov_len = data_len;
kv_len++;
}
}
nh.id = cpu_to_le64(id);
nh.data_len = cpu_to_le16(data_len);
nh.type = type;
nh.status = status;
trace_scoutfs_server_send_reply(conn->server->sb, &conn->sockname,
&conn->peername, &nh);
mutex_lock(&conn->send_mutex);
ret = scoutfs_sock_sendmsg(conn->sock, kv, kv_len);
mutex_unlock(&conn->send_mutex);
return ret;
}
#endif
void scoutfs_init_ment_to_net(struct scoutfs_net_manifest_entry *net_ment,
struct scoutfs_manifest_entry *ment)
{
@@ -1117,179 +1042,6 @@ int scoutfs_client_finish_compaction(struct super_block *sb, void *curs,
return ret;
}
#if 0
typedef int (*process_func_t)(struct server_connection *conn, u64 id,
u8 type, void *data, unsigned data_len);
/*
* Each request message gets its own concurrent blocking request processing
* context.
*/
static void scoutfs_server_process_func(struct work_struct *work)
{
struct server_request *req = container_of(work, struct server_request,
work);
struct server_connection *conn = req->conn;
static process_func_t process_funcs[] = {
[SCOUTFS_NET_ALLOC_INODES] = process_alloc_inodes,
[SCOUTFS_NET_ALLOC_EXTENT] = process_alloc_extent,
[SCOUTFS_NET_FREE_EXTENTS] = process_free_extents,
[SCOUTFS_NET_ALLOC_SEGNO] = process_alloc_segno,
[SCOUTFS_NET_RECORD_SEGMENT] = process_record_segment,
[SCOUTFS_NET_ADVANCE_SEQ] = process_advance_seq,
[SCOUTFS_NET_GET_LAST_SEQ] = process_get_last_seq,
[SCOUTFS_NET_GET_MANIFEST_ROOT] = process_get_manifest_root,
[SCOUTFS_NET_STATFS] = process_statfs,
};
struct scoutfs_net_header *nh = &req->nh;
process_func_t func;
int ret;
if (nh->type < ARRAY_SIZE(process_funcs))
func = process_funcs[nh->type];
else
func = NULL;
if (func)
ret = func(conn, le64_to_cpu(nh->id), nh->type, nh->data,
le16_to_cpu(nh->data_len));
else
ret = -EINVAL;
if (ret)
kernel_sock_shutdown(conn->sock, SHUT_RDWR);
/* process_one_work explicitly allows freeing work in its func */
kfree(req);
}
#endif
#if 0
/*
* Always block receiving from the socket. This owns the socket. If
* receive fails this shuts down and frees the socket.
*/
static void scoutfs_server_recv_func(struct work_struct *work)
{
struct server_connection *conn = container_of(work,
struct server_connection,
recv_work);
struct server_info *server = conn->server;
struct super_block *sb = server->sb;
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_super_block *super = &sbi->super;
struct socket *sock = conn->sock;
struct workqueue_struct *req_wq;
struct scoutfs_net_greeting greet;
struct scoutfs_net_header nh;
struct server_request *req;
bool passed_greeting;
unsigned data_len;
struct kvec kv;
int ret;
trace_scoutfs_server_recv_work_enter(sb, 0, 0);
req_wq = alloc_workqueue("scoutfs_server_requests",
WQ_NON_REENTRANT, 0);
if (!req_wq) {
ret = -ENOMEM;
goto out;
}
/* first bounce the greeting */
ret = scoutfs_sock_recvmsg(sock, &greet, sizeof(greet));
if (ret)
goto out;
/* we'll close conn after failed greeting to let client see ours */
passed_greeting = false;
if (greet.fsid != super->id) {
scoutfs_warn(sb, "client "SIN_FMT" has fsid 0x%llx, expected 0x%llx",
SIN_ARG(&conn->peername),
le64_to_cpu(greet.fsid),
le64_to_cpu(super->id));
} else if (greet.format_hash != super->format_hash) {
scoutfs_warn(sb, "client "SIN_FMT" has format hash 0x%llx, expected 0x%llx",
SIN_ARG(&conn->peername),
le64_to_cpu(greet.format_hash),
le64_to_cpu(super->format_hash));
} else {
passed_greeting = true;
}
greet.fsid = super->id;
greet.format_hash = super->format_hash;
kv.iov_base = &greet;
kv.iov_len = sizeof(greet);
ret = scoutfs_sock_sendmsg(sock, &kv, 1);
if (ret)
goto out;
for (;;) {
/* receive the header */
ret = scoutfs_sock_recvmsg(sock, &nh, sizeof(nh));
if (ret)
break;
if (!passed_greeting)
break;
trace_scoutfs_server_recv_request(conn->server->sb,
&conn->sockname,
&conn->peername, &nh);
/* XXX verify data_len isn't insane */
/* XXX test for bad messages */
data_len = le16_to_cpu(nh.data_len);
req = kmalloc(sizeof(struct server_request) + data_len,
GFP_NOFS);
if (!req) {
ret = -ENOMEM;
break;
}
ret = scoutfs_sock_recvmsg(sock, req->nh.data, data_len);
if (ret)
break;
req->conn = conn;
INIT_WORK(&req->work, scoutfs_server_process_func);
req->nh = nh;
queue_work(req_wq, &req->work);
/* req is freed by its work func */
req = NULL;
}
out:
scoutfs_info(sb, "server closing "SIN_FMT" -> "SIN_FMT,
SIN_ARG(&conn->peername), SIN_ARG(&conn->sockname));
/* make sure reply sending returns */
kernel_sock_shutdown(conn->sock, SHUT_RDWR);
/* wait for processing work to drain */
if (req_wq) {
drain_workqueue(req_wq);
destroy_workqueue(req_wq);
}
/* process_one_work explicitly allows freeing work in its func */
mutex_lock(&server->mutex);
sock_release(conn->sock);
list_del_init(&conn->head);
kfree(conn);
smp_mb();
wake_up_process(server->listen_task);
mutex_unlock(&server->mutex);
trace_scoutfs_server_recv_work_exit(sb, 0, ret);
}
#endif
/*
* This relies on the caller having read the current super and advanced
* its seq so that it's dirty. This will go away when we communicate
@@ -1305,16 +1057,6 @@ static int write_server_addr(struct super_block *sb, struct sockaddr_in *sin)
return scoutfs_write_dirty_super(sb);
}
#if 0
static bool barrier_list_empty_careful(struct list_head *list)
{
/* store caller's task state before loading wake condition */
smp_mb();
return list_empty_careful(list);
}
#endif
static scoutfs_net_request_t server_req_funcs[] = {
[SCOUTFS_NET_CMD_ALLOC_INODES] = server_alloc_inodes,
[SCOUTFS_NET_CMD_ALLOC_EXTENT] = server_alloc_extent,
-96
View File
@@ -1,96 +0,0 @@
/*
* Copyright (C) 2017 Versity Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/ioctls.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/in.h>
#include <net/sock.h>
#include <net/tcp.h>
#include "sock.h"
/*
* Some quick socket helper wrappers.
*/
static struct kvec *kvec_advance(struct kvec *kv, unsigned *kv_len,
unsigned bytes)
{
while (*kv_len && bytes) {
if (kv->iov_len <= bytes) {
bytes -= kv->iov_len;
kv++;
(*kv_len)--;
} else {
kv->iov_base += bytes;
kv->iov_len -= bytes;
bytes = 0;
}
}
return kv;
}
/*
* This can modify the kvec as it modifies the vec to continue after
* partial sends.
*/
int scoutfs_sock_sendmsg(struct socket *sock, struct kvec *kv, unsigned kv_len)
{
struct msghdr msg;
int ret;
while (kv_len) {
memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *)kv;
msg.msg_iovlen = kv_len;
msg.msg_flags = MSG_NOSIGNAL;
ret = kernel_sendmsg(sock, &msg, kv, kv_len,
iov_length((struct iovec *)kv, kv_len));
if (ret <= 0)
return -ECONNABORTED;
kv = kvec_advance(kv, &kv_len, ret);
}
return 0;
}
int scoutfs_sock_recvmsg(struct socket *sock, void *buf, unsigned len)
{
struct msghdr msg;
struct kvec kv;
int ret;
while (len) {
memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *)&kv;
msg.msg_iovlen = 1;
msg.msg_flags = MSG_NOSIGNAL;
kv.iov_base = buf;
kv.iov_len = len;
ret = kernel_recvmsg(sock, &msg, &kv, 1, len, msg.msg_flags);
if (ret <= 0)
return -ECONNABORTED;
len -= ret;
buf += ret;
}
return 0;
}
-7
View File
@@ -1,7 +0,0 @@
#ifndef _SCOUTFS_SOCK_H_
#define _SCOUTFS_SOCK_H_
int scoutfs_sock_recvmsg(struct socket *sock, void *buf, unsigned len);
int scoutfs_sock_sendmsg(struct socket *sock, struct kvec *kv, unsigned kv_len);
#endif