1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/source4/ntvfs/nbench/vfs_nbench.c
Andrew Tridgell 759da3b915 r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
large commit. I thought this was worthwhile to get done for
consistency.
(This used to be commit ec32b22ed5)
2007-10-10 13:09:15 -05:00

935 lines
21 KiB
C

/*
Unix SMB/CIFS implementation.
a pass-thru NTVFS module to record a NBENCH load file
Copyright (C) Andrew Tridgell 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
"passthru" in this module refers to the next level of NTVFS being used
*/
#include "includes.h"
#include "smb_server/smb_server.h"
/* this is stored in ntvfs_private */
struct nbench_private {
int log_fd;
};
/*
log one request to the nbench log
*/
static void nbench_log(struct smbsrv_request *req,
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
static void nbench_log(struct smbsrv_request *req,
const char *format, ...)
{
struct nbench_private *private = req->async_states->ntvfs->private_data;
va_list ap;
char *s = NULL;
va_start(ap, format);
vasprintf(&s, format, ap);
va_end(ap);
write(private->log_fd, s, strlen(s));
free(s);
}
/*
this pass through macro operates on request contexts, and disables
async calls.
async calls are a pain for the nbench module as it makes pulling the
status code and any result parameters much harder.
*/
#define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
status = ntvfs_async_state_push(req, par1, nbench_##op##_send, ntvfs); \
if (!NT_STATUS_IS_OK(status)) { \
return status; \
} \
} while (0)
#define PASS_THRU_REQ_POST_ASYNC(req) do { \
req->async_states->status = status; \
if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
req->async_states->send_fn(req); \
} \
} while (0)
#define PASS_THRU_REQ(ntvfs, req, op, par1, args) do { \
PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1); \
status = ntvfs_next_##op args; \
PASS_THRU_REQ_POST_ASYNC(req); \
} while (0)
#define PASS_THRU_REP_POST(req) do { \
ntvfs_async_state_pop(req); \
if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
req->async_states->send_fn(req); \
} \
} while (0)
/*
connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, const char *sharename)
{
struct nbench_private *nprivates;
NTSTATUS status;
char *logname = NULL;
nprivates = talloc(req->tcon, struct nbench_private);
if (!nprivates) {
return NT_STATUS_NO_MEMORY;
}
asprintf(&logname, "/tmp/nbenchlog%d.%u", ntvfs->depth, getpid());
nprivates->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
free(logname);
if (nprivates->log_fd == -1) {
DEBUG(0,("Failed to open nbench log\n"));
return NT_STATUS_UNSUCCESSFUL;
}
ntvfs->private_data = nprivates;
status = ntvfs_next_connect(ntvfs, req, sharename);
return status;
}
/*
disconnect from a share
*/
static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs,
struct smbsrv_tcon *tcon)
{
struct nbench_private *nprivates = ntvfs->private_data;
NTSTATUS status;
close(nprivates->log_fd);
status = ntvfs_next_disconnect(ntvfs, tcon);
return status;
}
/*
delete a file - the dirtype specifies the file types to include in the search.
The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
*/
static void nbench_unlink_send(struct smbsrv_request *req)
{
struct smb_unlink *unl = req->async_states->private_data;
nbench_log(req, "Unlink \"%s\" 0x%x %s\n",
unl->in.pattern, unl->in.attrib,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_unlink *unl)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
return status;
}
/*
ioctl interface
*/
static void nbench_ioctl_send(struct smbsrv_request *req)
{
nbench_log(req, "Ioctl - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_ioctl *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
return status;
}
/*
check if a directory exists
*/
static void nbench_chkpath_send(struct smbsrv_request *req)
{
struct smb_chkpath *cp = req->async_states->private_data;
nbench_log(req, "Chkpath \"%s\" %s\n",
cp->in.path,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_chkpath *cp)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, chkpath, cp, (ntvfs, req, cp));
return status;
}
/*
return info on a pathname
*/
static void nbench_qpathinfo_send(struct smbsrv_request *req)
{
union smb_fileinfo *info = req->async_states->private_data;
nbench_log(req, "QUERY_PATH_INFORMATION \"%s\" %d %s\n",
info->generic.in.fname,
info->generic.level,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_fileinfo *info)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
return status;
}
/*
query info on a open file
*/
static void nbench_qfileinfo_send(struct smbsrv_request *req)
{
union smb_fileinfo *info = req->async_states->private_data;
nbench_log(req, "QUERY_FILE_INFORMATION %d %d %s\n",
info->generic.in.fnum,
info->generic.level,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_fileinfo *info)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
return status;
}
/*
set info on a pathname
*/
static void nbench_setpathinfo_send(struct smbsrv_request *req)
{
union smb_setfileinfo *st = req->async_states->private_data;
nbench_log(req, "SET_PATH_INFORMATION \"%s\" %d %s\n",
st->generic.file.fname,
st->generic.level,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_setfileinfo *st)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
return status;
}
/*
open a file
*/
static void nbench_openfile_send(struct smbsrv_request *req)
{
union smb_open *io = req->async_states->private_data;
switch (io->generic.level) {
case RAW_OPEN_NTCREATEX:
if (!NT_STATUS_IS_OK(req->async_states->status)) {
ZERO_STRUCT(io->ntcreatex.out);
}
nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n",
io->ntcreatex.in.fname,
io->ntcreatex.in.create_options,
io->ntcreatex.in.open_disposition,
io->ntcreatex.out.fnum,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Open-%d - NOT HANDLED\n",
io->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_openfile(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_open *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, openfile, io, (ntvfs, req, io));
return status;
}
/*
create a directory
*/
static void nbench_mkdir_send(struct smbsrv_request *req)
{
nbench_log(req, "Mkdir - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_mkdir *md)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
return status;
}
/*
remove a directory
*/
static void nbench_rmdir_send(struct smbsrv_request *req)
{
struct smb_rmdir *rd = req->async_states->private_data;
nbench_log(req, "Rmdir \"%s\" %s\n",
rd->in.path,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_rmdir *rd)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
return status;
}
/*
rename a set of files
*/
static void nbench_rename_send(struct smbsrv_request *req)
{
union smb_rename *ren = req->async_states->private_data;
switch (ren->generic.level) {
case RAW_RENAME_RENAME:
nbench_log(req, "Rename \"%s\" \"%s\" %s\n",
ren->rename.in.pattern1,
ren->rename.in.pattern2,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Rename-%d - NOT HANDLED\n",
ren->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_rename *ren)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, rename, ren, (ntvfs, req, ren));
return status;
}
/*
copy a set of files
*/
static void nbench_copy_send(struct smbsrv_request *req)
{
nbench_log(req, "Copy - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_copy *cp)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
return status;
}
/*
read from a file
*/
static void nbench_read_send(struct smbsrv_request *req)
{
union smb_read *rd = req->async_states->private_data;
switch (rd->generic.level) {
case RAW_READ_READX:
if (!NT_STATUS_IS_OK(req->async_states->status)) {
ZERO_STRUCT(rd->readx.out);
}
nbench_log(req, "ReadX %d %d %d %d %s\n",
rd->readx.in.fnum,
(int)rd->readx.in.offset,
rd->readx.in.maxcnt,
rd->readx.out.nread,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Read-%d - NOT HANDLED\n",
rd->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_read *rd)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, read, rd, (ntvfs, req, rd));
return status;
}
/*
write to a file
*/
static void nbench_write_send(struct smbsrv_request *req)
{
union smb_write *wr = req->async_states->private_data;
switch (wr->generic.level) {
case RAW_WRITE_WRITEX:
if (!NT_STATUS_IS_OK(req->async_states->status)) {
ZERO_STRUCT(wr->writex.out);
}
nbench_log(req, "WriteX %d %d %d %d %s\n",
wr->writex.in.fnum,
(int)wr->writex.in.offset,
wr->writex.in.count,
wr->writex.out.nwritten,
get_nt_error_c_code(req->async_states->status));
break;
case RAW_WRITE_WRITE:
if (!NT_STATUS_IS_OK(req->async_states->status)) {
ZERO_STRUCT(wr->write.out);
}
nbench_log(req, "Write %d %d %d %d %s\n",
wr->write.in.fnum,
wr->write.in.offset,
wr->write.in.count,
wr->write.out.nwritten,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Write-%d - NOT HANDLED\n",
wr->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_write *wr)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, write, wr, (ntvfs, req, wr));
return status;
}
/*
seek in a file
*/
static void nbench_seek_send(struct smbsrv_request *req)
{
nbench_log(req, "Seek - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_seek *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
return status;
}
/*
flush a file
*/
static void nbench_flush_send(struct smbsrv_request *req)
{
struct smb_flush *io = req->async_states->private_data;
nbench_log(req, "Flush %d %s\n",
io->in.fnum,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_flush *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
return status;
}
/*
close a file
*/
static void nbench_close_send(struct smbsrv_request *req)
{
union smb_close *io = req->async_states->private_data;
switch (io->generic.level) {
case RAW_CLOSE_CLOSE:
nbench_log(req, "Close %d %s\n",
io->close.in.fnum,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Close-%d - NOT HANDLED\n",
io->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_close *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
return status;
}
/*
exit - closing files
*/
static void nbench_exit_send(struct smbsrv_request *req)
{
nbench_log(req, "Exit - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
return status;
}
/*
logoff - closing files
*/
static void nbench_logoff_send(struct smbsrv_request *req)
{
nbench_log(req, "Logoff - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
return status;
}
/*
async_setup - send fn
*/
static void nbench_async_setup_send(struct smbsrv_request *req)
{
PASS_THRU_REP_POST(req);
}
/*
async setup
*/
static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req,
void *private)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, async_setup, NULL, (ntvfs, req, private));
return status;
}
static void nbench_cancel_send(struct smbsrv_request *req)
{
PASS_THRU_REP_POST(req);
}
/*
cancel an existing async request
*/
static NTSTATUS nbench_cancel(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, cancel, NULL, (ntvfs, req));
return status;
}
/*
lock a byte range
*/
static void nbench_lock_send(struct smbsrv_request *req)
{
union smb_lock *lck = req->async_states->private_data;
if (lck->generic.level == RAW_LOCK_LOCKX &&
lck->lockx.in.lock_cnt == 1 &&
lck->lockx.in.ulock_cnt == 0) {
nbench_log(req, "LockX %d %d %d %s\n",
lck->lockx.in.fnum,
(int)lck->lockx.in.locks[0].offset,
(int)lck->lockx.in.locks[0].count,
get_nt_error_c_code(req->async_states->status));
} else if (lck->generic.level == RAW_LOCK_LOCKX &&
lck->lockx.in.ulock_cnt == 1) {
nbench_log(req, "UnlockX %d %d %d %s\n",
lck->lockx.in.fnum,
(int)lck->lockx.in.locks[0].offset,
(int)lck->lockx.in.locks[0].count,
get_nt_error_c_code(req->async_states->status));
} else {
nbench_log(req, "Lock-%d - NOT HANDLED\n", lck->generic.level);
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_lock *lck)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, lock, lck, (ntvfs, req, lck));
return status;
}
/*
set info on a open file
*/
static void nbench_setfileinfo_send(struct smbsrv_request *req)
{
union smb_setfileinfo *info = req->async_states->private_data;
nbench_log(req, "SET_FILE_INFORMATION %d %d %s\n",
info->generic.file.fnum,
info->generic.level,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req,
union smb_setfileinfo *info)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
return status;
}
/*
return filesystem space info
*/
static void nbench_fsinfo_send(struct smbsrv_request *req)
{
union smb_fsinfo *fs = req->async_states->private_data;
nbench_log(req, "QUERY_FS_INFORMATION %d %s\n",
fs->generic.level,
get_nt_error_c_code(req->async_states->status));
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_fsinfo *fs)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
return status;
}
/*
return print queue info
*/
static void nbench_lpq_send(struct smbsrv_request *req)
{
union smb_lpq *lpq = req->async_states->private_data;
nbench_log(req, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_lpq *lpq)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
return status;
}
/*
list files in a directory matching a wildcard pattern
*/
static void nbench_search_first_send(struct smbsrv_request *req)
{
union smb_search_first *io = req->async_states->private_data;
switch (io->generic.level) {
case RAW_SEARCH_BOTH_DIRECTORY_INFO:
if (NT_STATUS_IS_ERR(req->async_states->status)) {
ZERO_STRUCT(io->t2ffirst.out);
}
nbench_log(req, "FIND_FIRST \"%s\" %d %d %d %s\n",
io->t2ffirst.in.pattern,
io->generic.level,
io->t2ffirst.in.max_count,
io->t2ffirst.out.count,
get_nt_error_c_code(req->async_states->status));
break;
default:
nbench_log(req, "Search-%d - NOT HANDLED\n", io->generic.level);
break;
}
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_search_first *io,
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, search_first, io, (ntvfs, req, io, search_private, callback));
return status;
}
/* continue a search */
static void nbench_search_next_send(struct smbsrv_request *req)
{
union smb_search_next *io = req->async_states->private_data;
nbench_log(req, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_search_next *io,
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, search_next, io, (ntvfs, req, io, search_private, callback));
return status;
}
/* close a search */
static void nbench_search_close_send(struct smbsrv_request *req)
{
union smb_search_close *io = req->async_states->private_data;
nbench_log(req, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_search_close *io)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
return status;
}
/* SMBtrans - not used on file shares */
static void nbench_trans_send(struct smbsrv_request *req)
{
nbench_log(req, "Trans - NOT HANDLED\n");
PASS_THRU_REP_POST(req);
}
static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_trans2 *trans2)
{
NTSTATUS status;
PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
return status;
}
/*
initialise the nbench backend, registering ourselves with the ntvfs subsystem
*/
NTSTATUS ntvfs_nbench_init(void)
{
NTSTATUS ret;
struct ntvfs_ops ops;
ZERO_STRUCT(ops);
/* fill in the name and type */
ops.name = "nbench";
ops.type = NTVFS_DISK;
/* fill in all the operations */
ops.connect = nbench_connect;
ops.disconnect = nbench_disconnect;
ops.unlink = nbench_unlink;
ops.chkpath = nbench_chkpath;
ops.qpathinfo = nbench_qpathinfo;
ops.setpathinfo = nbench_setpathinfo;
ops.openfile = nbench_openfile;
ops.mkdir = nbench_mkdir;
ops.rmdir = nbench_rmdir;
ops.rename = nbench_rename;
ops.copy = nbench_copy;
ops.ioctl = nbench_ioctl;
ops.read = nbench_read;
ops.write = nbench_write;
ops.seek = nbench_seek;
ops.flush = nbench_flush;
ops.close = nbench_close;
ops.exit = nbench_exit;
ops.lock = nbench_lock;
ops.setfileinfo = nbench_setfileinfo;
ops.qfileinfo = nbench_qfileinfo;
ops.fsinfo = nbench_fsinfo;
ops.lpq = nbench_lpq;
ops.search_first = nbench_search_first;
ops.search_next = nbench_search_next;
ops.search_close = nbench_search_close;
ops.trans = nbench_trans;
ops.logoff = nbench_logoff;
ops.async_setup = nbench_async_setup;
ops.cancel = nbench_cancel;
/* we don't register a trans2 handler as we want to be able to
log individual trans2 requests */
ops.trans2 = NULL;
/* register ourselves with the NTVFS subsystem. */
ret = ntvfs_register(&ops);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(0,("Failed to register nbench backend!\n"));
}
return ret;
}