Move KV FS header into a separate file

master
Vitaliy Filippov 2024-02-03 15:01:44 +03:00
parent e5bb986164
commit 7c235c9103
16 changed files with 159 additions and 197 deletions

View File

@ -6,8 +6,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs_kv.h"
nfsstat3 vitastor_nfs_map_err(int err)
{
@ -140,5 +140,5 @@ uint64_t kv_fh_inode(const std::string & fh)
bool kv_fh_valid(const std::string & fh)
{
return fh == KV_ROOT_HANDLE || fh.size() == 9 && fh[0] == 'S' || fh.size() > 17 && fh[0] == 'I';
return fh == NFS_ROOT_HANDLE || fh.size() == 9 && fh[0] == 'S' || fh.size() > 17 && fh[0] == 'I';
}

106
src/nfs_kv.h Normal file
View File

@ -0,0 +1,106 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
//
// NFS proxy over VitastorKV database - header
#pragma once
#include "nfs/nfs.h"
#define KV_ROOT_INODE 1
#define KV_NEXT_ID_KEY "id"
#define SHARED_FILE_MAGIC_V1 0x711A5158A6EDF17E
struct nfs_kv_write_state;
struct list_cookie_t
{
uint64_t dir_ino, cookieverf, cookie;
};
inline bool operator < (const list_cookie_t & a, const list_cookie_t & b)
{
return a.dir_ino < b.dir_ino || a.dir_ino == b.dir_ino &&
(a.cookieverf < b.cookieverf || a.cookieverf == b.cookieverf && a.cookie < b.cookie);
};
struct list_cookie_val_t
{
std::string key;
};
struct shared_alloc_queue_t
{
nfs_kv_write_state *st;
int state;
uint64_t size;
};
struct inode_extend_t
{
int refcnt = 0;
uint64_t cur_extend = 0, next_extend = 0, done_extend = 0;
std::vector<std::function<void()>> waiters;
};
struct kv_fs_state_t
{
std::map<list_cookie_t, list_cookie_val_t> list_cookies;
uint64_t fs_next_id = 0, fs_allocated_id = 0;
std::vector<uint64_t> unallocated_ids;
std::vector<shared_alloc_queue_t> allocating_shared;
uint64_t cur_shared_inode = 0, cur_shared_offset = 0;
std::map<inode_t, inode_extend_t> extends;
};
struct shared_file_header_t
{
uint64_t magic = 0;
uint64_t inode = 0;
uint64_t size = 0;
};
nfsstat3 vitastor_nfs_map_err(int err);
nfstime3 nfstime_from_str(const std::string & s);
std::string nfstime_to_str(nfstime3 t);
int kv_map_type(const std::string & type);
fattr3 get_kv_attributes(nfs_client_t *self, uint64_t ino, json11::Json attrs);
std::string kv_direntry_key(uint64_t dir_ino, const std::string & filename);
std::string kv_direntry_filename(const std::string & key);
std::string kv_inode_key(uint64_t ino);
std::string kv_fh(uint64_t ino);
uint64_t kv_fh_inode(const std::string & fh);
bool kv_fh_valid(const std::string & fh);
void allocate_new_id(nfs_client_t *self, std::function<void(int res, uint64_t new_id)> cb);
void kv_read_inode(nfs_client_t *self, uint64_t ino,
std::function<void(int res, const std::string & value, json11::Json ientry)> cb,
bool allow_cache = false);
uint64_t align_shared_size(nfs_client_t *self, uint64_t size);
int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_setattr_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_lookup_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readlink_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_read_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_write_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_create_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_mkdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_symlink_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_mknod_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_remove_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_rmdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_rename_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_link_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readdirplus_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_fsstat_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_fsinfo_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_pathconf_proc(void *opaque, rpc_op_t *rop);
int nfs3_access_proc(void *opaque, rpc_op_t *rop);
int nfs3_null_proc(void *opaque, rpc_op_t *rop);
int nfs3_commit_proc(void *opaque, rpc_op_t *rop);
int mount3_mnt_proc(void *opaque, rpc_op_t *rop);
int mount3_dump_proc(void *opaque, rpc_op_t *rop);
int mount3_umnt_proc(void *opaque, rpc_op_t *rop);
int mount3_umntall_proc(void *opaque, rpc_op_t *rop);
int mount3_export_proc(void *opaque, rpc_op_t *rop);

View File

@ -6,21 +6,17 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
void allocate_new_id(nfs_client_t *self, std::function<void(int res, uint64_t new_id)> cb)
{
if (self->parent->fs_next_id <= self->parent->fs_allocated_id)
if (self->parent->kvfs->fs_next_id <= self->parent->kvfs->fs_allocated_id)
{
cb(0, self->parent->fs_next_id++);
cb(0, self->parent->kvfs->fs_next_id++);
return;
}
else if (self->parent->fs_next_id > self->parent->fs_inode_count)
else if (self->parent->kvfs->fs_next_id > self->parent->fs_inode_count)
{
cb(-ENOSPC, 0);
return;
@ -60,8 +56,8 @@ void allocate_new_id(nfs_client_t *self, std::function<void(int res, uint64_t ne
}
else
{
self->parent->fs_next_id = prev_val+2;
self->parent->fs_allocated_id = new_val;
self->parent->kvfs->fs_next_id = prev_val+2;
self->parent->kvfs->fs_allocated_id = new_val;
cb(0, prev_val+1);
}
}, [prev_val](int res, const std::string & value)
@ -120,7 +116,7 @@ static void kv_do_create(kv_create_state *st)
{
if (res < 0)
{
st->self->parent->unallocated_ids.push_back(st->new_id);
st->self->parent->kvfs->unallocated_ids.push_back(st->new_id);
if (res == -EAGAIN)
{
if (st->dup_ino)
@ -150,7 +146,7 @@ static void kv_do_create(kv_create_state *st)
{
if (!del_res)
{
st->self->parent->unallocated_ids.push_back(st->new_id);
st->self->parent->kvfs->unallocated_ids.push_back(st->new_id);
}
auto cb = std::move(st->cb);
cb(res);

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
// Get file system statistics
int kv_nfs3_fsstat_proc(void *opaque, rpc_op_t *rop)
@ -57,7 +52,7 @@ int kv_nfs3_fsinfo_proc(void *opaque, rpc_op_t *rop)
FSINFO3res *reply = (FSINFO3res*)rop->reply;
if (self->parent->trace)
fprintf(stderr, "[%d] FSINFO %s\n", self->nfs_fd, std::string(args->fsroot).c_str());
if (args->fsroot != KV_ROOT_HANDLE)
if (args->fsroot != NFS_ROOT_HANDLE)
{
*reply = (FSINFO3res){ .status = NFS3ERR_INVAL };
}
@ -98,7 +93,7 @@ int kv_nfs3_pathconf_proc(void *opaque, rpc_op_t *rop)
PATHCONF3res *reply = (PATHCONF3res*)rop->reply;
if (self->parent->trace)
fprintf(stderr, "[%d] PATHCONF %s\n", self->nfs_fd, std::string(args->object).c_str());
if (args->object != KV_ROOT_HANDLE)
if (args->object != NFS_ROOT_HANDLE)
{
*reply = (PATHCONF3res){ .status = NFS3ERR_INVAL };
}

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
// Attributes are always stored in the inode
void kv_read_inode(nfs_client_t *self, uint64_t ino,

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
struct nfs_kv_link_state
{

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
int kv_nfs3_lookup_proc(void *opaque, rpc_op_t *rop)
{
@ -77,7 +72,7 @@ int kv_nfs3_readlink_proc(void *opaque, rpc_op_t *rop)
if (self->parent->trace)
fprintf(stderr, "[%d] READLINK %ju\n", self->nfs_fd, kv_fh_inode(args->symlink));
READLINK3res *reply = (READLINK3res*)rop->reply;
if (!kv_fh_valid(args->symlink) || args->symlink == KV_ROOT_HANDLE)
if (!kv_fh_valid(args->symlink) || args->symlink == NFS_ROOT_HANDLE)
{
// Invalid filehandle or trying to read symlink from root entry
*reply = (READLINK3res){ .status = NFS3ERR_INVAL };

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
struct nfs_kv_read_state
{

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
static unsigned len_pad4(unsigned len)
{
@ -190,8 +185,8 @@ resume_2:
st->start = st->prefix;
if (st->cookie > 1)
{
auto lc_it = st->self->parent->list_cookies.find((list_cookie_t){ st->dir_ino, st->cookieverf, st->cookie });
if (lc_it != st->self->parent->list_cookies.end())
auto lc_it = st->self->parent->kvfs->list_cookies.find((list_cookie_t){ st->dir_ino, st->cookieverf, st->cookie });
if (lc_it != st->self->parent->kvfs->list_cookies.end())
{
st->start = lc_it->second.key;
st->to_skip = 1;
@ -211,18 +206,18 @@ resume_2:
st->cookieverf = ((uint64_t)lrand48() | ((uint64_t)lrand48() << 31) | ((uint64_t)lrand48() << 62));
}
{
auto lc_it = st->self->parent->list_cookies.lower_bound((list_cookie_t){ st->dir_ino, st->cookieverf, 0 });
if (lc_it != st->self->parent->list_cookies.end() &&
auto lc_it = st->self->parent->kvfs->list_cookies.lower_bound((list_cookie_t){ st->dir_ino, st->cookieverf, 0 });
if (lc_it != st->self->parent->kvfs->list_cookies.end() &&
lc_it->first.dir_ino == st->dir_ino &&
lc_it->first.cookieverf == st->cookieverf &&
lc_it->first.cookie < st->cookie)
{
auto lc_start = lc_it;
while (lc_it != st->self->parent->list_cookies.end() && lc_it->first.cookieverf == st->cookieverf)
while (lc_it != st->self->parent->kvfs->list_cookies.end() && lc_it->first.cookieverf == st->cookieverf)
{
lc_it++;
}
st->self->parent->list_cookies.erase(lc_start, lc_it);
st->self->parent->kvfs->list_cookies.erase(lc_start, lc_it);
}
}
st->getattr_cur = st->entries.size();
@ -281,7 +276,7 @@ resume_3:
entry->name = xdr_copy_string(st->rop->xdrs, name);
entry->fileid = ino;
entry->cookie = st->offset++;
st->self->parent->list_cookies[(list_cookie_t){ st->dir_ino, st->cookieverf, entry->cookie }] = { .key = entry->name };
st->self->parent->kvfs->list_cookies[(list_cookie_t){ st->dir_ino, st->cookieverf, entry->cookie }] = { .key = entry->name };
if (st->is_plus)
{
entry->name_handle = (post_op_fh3){

View File

@ -5,12 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "nfs_kv.h"
#include "cli.h"
struct kv_del_state

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
struct nfs_kv_rename_state
{

View File

@ -5,12 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "nfs_kv.h"
#include "cli.h"
struct nfs_kv_setattr_state

View File

@ -5,13 +5,8 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
#include "nfs_kv.h"
struct nfs_rmw_t
{
@ -62,15 +57,15 @@ static void nfs_kv_continue_write(nfs_kv_write_state *st, int state);
static void finish_allocate_shared(nfs_client_t *self, int res)
{
std::vector<shared_alloc_queue_t> waiting;
waiting.swap(self->parent->allocating_shared);
waiting.swap(self->parent->kvfs->allocating_shared);
for (auto & w: waiting)
{
w.st->res = res;
if (res == 0)
{
w.st->shared_inode = self->parent->cur_shared_inode;
w.st->shared_offset = self->parent->cur_shared_offset;
self->parent->cur_shared_offset += (w.size + self->parent->pool_alignment-1) & ~(self->parent->pool_alignment-1);
w.st->shared_inode = self->parent->kvfs->cur_shared_inode;
w.st->shared_offset = self->parent->kvfs->cur_shared_offset;
self->parent->kvfs->cur_shared_offset += (w.size + self->parent->pool_alignment-1) & ~(self->parent->pool_alignment-1);
}
nfs_kv_continue_write(w.st, w.state);
}
@ -78,10 +73,10 @@ static void finish_allocate_shared(nfs_client_t *self, int res)
static void allocate_shared_inode(nfs_kv_write_state *st, int state, uint64_t size)
{
if (st->self->parent->cur_shared_inode == 0)
if (st->self->parent->kvfs->cur_shared_inode == 0)
{
st->self->parent->allocating_shared.push_back({ st, state, size });
if (st->self->parent->allocating_shared.size() > 1)
st->self->parent->kvfs->allocating_shared.push_back({ st, state, size });
if (st->self->parent->kvfs->allocating_shared.size() > 1)
{
return;
}
@ -92,15 +87,15 @@ static void allocate_shared_inode(nfs_kv_write_state *st, int state, uint64_t si
finish_allocate_shared(st->self, res);
return;
}
st->self->parent->cur_shared_inode = new_id;
st->self->parent->cur_shared_offset = 0;
st->self->parent->kvfs->cur_shared_inode = new_id;
st->self->parent->kvfs->cur_shared_offset = 0;
st->self->parent->db->set(
kv_inode_key(new_id), json11::Json(json11::Json::object{ { "type", "shared" } }).dump(),
[st](int res)
{
if (res < 0)
{
st->self->parent->cur_shared_inode = 0;
st->self->parent->kvfs->cur_shared_inode = 0;
}
finish_allocate_shared(st->self, res);
},
@ -727,7 +722,7 @@ resume_11:
st->ientry["size"].uint64_value() < st->new_size ||
st->ientry["shared_ino"].uint64_value() != 0)
{
st->ext = &st->self->parent->extends[st->ino];
st->ext = &st->self->parent->kvfs->extends[st->ino];
st->ext->refcnt++;
resume_12:
if (st->ext->next_extend < st->new_size)
@ -752,7 +747,7 @@ resume_13:
assert(st->ext->refcnt >= 0);
if (st->ext->refcnt == 0)
{
st->self->parent->extends.erase(st->ino);
st->self->parent->kvfs->extends.erase(st->ino);
}
}
if (st->res == -EAGAIN)

View File

@ -5,13 +5,10 @@
#include <sys/time.h>
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs/nfs.h"
#include "cli.h"
nfsstat3 vitastor_nfs_map_err(int err);
int nfs3_null_proc(void *opaque, rpc_op_t *rop)
{
@ -61,7 +58,7 @@ int mount3_mnt_proc(void *opaque, rpc_op_t *rop)
nfs_mountres3 *reply = (nfs_mountres3*)rop->reply;
u_int flavor = RPC_AUTH_NONE;
reply->fhs_status = MNT3_OK;
reply->mountinfo.fhandle = xdr_copy_string(rop->xdrs, KV_ROOT_HANDLE);
reply->mountinfo.fhandle = xdr_copy_string(rop->xdrs, NFS_ROOT_HANDLE);
reply->mountinfo.auth_flavors.auth_flavors_len = 1;
reply->mountinfo.auth_flavors.auth_flavors_val = (u_int*)xdr_copy_string(rop->xdrs, (char*)&flavor, sizeof(u_int)).data;
rpc_queue_reply(rop);

View File

@ -21,6 +21,7 @@
#include "addr_util.h"
#include "str_util.h"
#include "nfs_proxy.h"
#include "nfs_kv.h"
#include "http_client.h"
#include "cli.h"
@ -192,6 +193,7 @@ void nfs_proxy_t::run(json11::Json cfg)
fs_base_inode = ((uint64_t)default_pool_id << (64-POOL_ID_BITS));
fs_inode_count = ((uint64_t)1 << (64-POOL_ID_BITS)) - 1;
shared_inode_threshold = pool_block_size;
kvfs = new kv_fs_state_t;
}
// Self-register portmap and NFS
pmap.reg_ports.insert((portmap_id_t){
@ -266,9 +268,13 @@ void nfs_proxy_t::run(json11::Json cfg)
}
// Destroy the client
cli->flush();
delete kvfs;
delete db;
delete cli;
delete epmgr;
delete ringloop;
kvfs = NULL;
db = NULL;
cli = NULL;
epmgr = NULL;
ringloop = NULL;

View File

@ -6,6 +6,7 @@
#include "nfs/xdr_impl.h"
#include "kv_db.h"
#define NFS_ROOT_HANDLE "R"
#define RPC_INIT_BUF_SIZE 32768
#define MAX_REQUEST_SIZE 128*1024*1024
#define TRUE 1
@ -13,37 +14,7 @@
class cli_tool_t;
struct list_cookie_t
{
uint64_t dir_ino, cookieverf, cookie;
};
inline bool operator < (const list_cookie_t & a, const list_cookie_t & b)
{
return a.dir_ino < b.dir_ino || a.dir_ino == b.dir_ino &&
(a.cookieverf < b.cookieverf || a.cookieverf == b.cookieverf && a.cookie < b.cookie);
};
struct list_cookie_val_t
{
std::string key;
};
struct nfs_kv_write_state;
struct shared_alloc_queue_t
{
nfs_kv_write_state *st;
int state;
uint64_t size;
};
struct inode_extend_t
{
int refcnt = 0;
uint64_t cur_extend = 0, next_extend = 0, done_extend = 0;
std::vector<std::function<void()>> waiters;
};
struct kv_fs_state_t;
class nfs_proxy_t
{
@ -73,12 +44,7 @@ public:
cluster_client_t *cli = NULL;
cli_tool_t *cmd = NULL;
kv_dbw_t *db = NULL;
std::map<list_cookie_t, list_cookie_val_t> list_cookies;
uint64_t fs_next_id = 0, fs_allocated_id = 0;
std::vector<uint64_t> unallocated_ids;
std::vector<shared_alloc_queue_t> allocating_shared;
uint64_t cur_shared_inode = 0, cur_shared_offset = 0;
std::map<inode_t, inode_extend_t> extends;
kv_fs_state_t *kvfs = NULL;
std::vector<XDR*> xdr_pool;
@ -98,7 +64,6 @@ public:
void daemonize();
};
// FIXME: Move to "proto"
struct rpc_cur_buffer_t
{
uint8_t *buf;
@ -156,63 +121,3 @@ public:
bool deref();
void stop();
};
// FIXME: Move to "impl"
#include "nfs/nfs.h"
#define KV_ROOT_INODE 1
#define KV_NEXT_ID_KEY "id"
#define KV_ROOT_HANDLE "R"
#define SHARED_FILE_MAGIC_V1 0x711A5158A6EDF17E
struct shared_file_header_t
{
uint64_t magic = 0;
uint64_t inode = 0;
uint64_t size = 0;
};
nfsstat3 vitastor_nfs_map_err(int err);
nfstime3 nfstime_from_str(const std::string & s);
std::string nfstime_to_str(nfstime3 t);
int kv_map_type(const std::string & type);
fattr3 get_kv_attributes(nfs_client_t *self, uint64_t ino, json11::Json attrs);
std::string kv_direntry_key(uint64_t dir_ino, const std::string & filename);
std::string kv_direntry_filename(const std::string & key);
std::string kv_inode_key(uint64_t ino);
std::string kv_fh(uint64_t ino);
uint64_t kv_fh_inode(const std::string & fh);
bool kv_fh_valid(const std::string & fh);
void allocate_new_id(nfs_client_t *self, std::function<void(int res, uint64_t new_id)> cb);
void kv_read_inode(nfs_client_t *self, uint64_t ino,
std::function<void(int res, const std::string & value, json11::Json ientry)> cb,
bool allow_cache = false);
uint64_t align_shared_size(nfs_client_t *self, uint64_t size);
int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_setattr_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_lookup_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readlink_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_read_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_write_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_create_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_mkdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_symlink_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_mknod_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_remove_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_rmdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_rename_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_link_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readdir_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_readdirplus_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_fsstat_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_fsinfo_proc(void *opaque, rpc_op_t *rop);
int kv_nfs3_pathconf_proc(void *opaque, rpc_op_t *rop);
int nfs3_access_proc(void *opaque, rpc_op_t *rop);
int nfs3_null_proc(void *opaque, rpc_op_t *rop);
int nfs3_commit_proc(void *opaque, rpc_op_t *rop);
int mount3_mnt_proc(void *opaque, rpc_op_t *rop);
int mount3_dump_proc(void *opaque, rpc_op_t *rop);
int mount3_umnt_proc(void *opaque, rpc_op_t *rop);
int mount3_umntall_proc(void *opaque, rpc_op_t *rop);
int mount3_export_proc(void *opaque, rpc_op_t *rop);