2 Copyright (C) by Ronnie Sahlberg <sahlberg@samba.org> 2008
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #define _FILE_OFFSET_BITS 64
29 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
33 static char rw_buf[65536];
41 static void nfs3_deltree(struct dbench_op *op);
43 static void nfs3_cleanup(struct child_struct *child)
49 asprintf(&dname, "/clients/client%d", child->id);
56 static void nfs3_setup(struct child_struct *child)
58 const char *status = "0x00000000";
61 child->rate.last_time = timeval_current();
62 child->rate.last_bytes = 0;
65 srandom(getpid() ^ time(NULL));
66 child->private = nfsio_connect(options.server, options.export, options.protocol);
68 if (child->private == NULL) {
70 printf("nfsio_connect() failed\n");
74 /* create '/clients' */
75 res = nfsio_lookup(child->private, "/clients", NULL);
76 if (res == NFS3ERR_NOENT) {
77 res = nfsio_mkdir(child->private, "/clients");
78 if( (res != NFS3_OK) &&
79 (res != NFS3ERR_EXIST) ) {
80 printf("Failed to create '/clients' directory. res:%u\n", res);
87 static void dirent_cb(struct entryplus3 *e, void *private_data)
89 struct cb_data *cbd = private_data;
93 if (!strcmp(cbd->dirname,".")) {
96 if (!strcmp(cbd->dirname,"..")) {
100 asprintf(&objname, "%s/%s", cbd->dirname, e->name);
101 if (objname == NULL) {
102 printf("Failed to talloc ne object name in dirent_cb\n");
106 if (e->name_attributes.post_op_attr_u.attributes.type == NF3DIR) {
107 struct cb_data *new_cbd = malloc(sizeof(struct cb_data));
109 new_cbd->nfsio = cbd->nfsio;
110 new_cbd->dirname = strdup(objname);
112 nfsio_readdirplus(cbd->nfsio, objname, dirent_cb, new_cbd);
114 res = nfsio_rmdir(cbd->nfsio, objname);
115 if (res != NFS3_OK) {
116 printf("Failed to remove object : \"%s\" %s (%d)\n", objname, nfs_error(res), res);
118 free(new_cbd->dirname);
125 free(new_cbd->dirname);
130 res = nfsio_remove(cbd->nfsio, objname);
131 if (res != NFS3_OK) {
132 printf("Failed to remove object : \"%s\" %s %d\n", objname, nfs_error(res), res);
140 static void nfs3_deltree(struct dbench_op *op)
145 cbd = malloc(sizeof(struct cb_data));
147 cbd->nfsio = op->child->private;
148 cbd->dirname = discard_const(op->fname);
150 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
151 if (res != NFS3ERR_NOENT) {
152 nfsio_readdirplus(cbd->nfsio, cbd->dirname, dirent_cb, cbd);
153 nfsio_rmdir(cbd->nfsio, cbd->dirname);
156 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
157 if (res != NFS3ERR_NOENT) {
158 printf("Directory \"%s\" not empty. Aborting\n", cbd->dirname);
165 static int check_status(int status, const char *expected)
167 if (strcmp(expected, "*") == 0){
170 if (strncmp(expected, "0x", 2) == 0) {
171 return status == strtol(expected, NULL, 16);
176 static void failed(struct child_struct *child)
179 printf("ERROR: child %d failed at line %d\n", child->id, child->line);
183 static void nfs3_getattr(struct dbench_op *op)
187 res = nfsio_getattr(op->child->private, op->fname, NULL);
188 if (!check_status(res, op->status)) {
189 printf("[%d] GETATTR \"%s\" failed (%x) - expected %s\n",
190 op->child->line, op->fname, res, op->status);
196 static void nfs3_lookup(struct dbench_op *op)
200 res = nfsio_lookup(op->child->private, op->fname, NULL);
201 if (!check_status(res, op->status)) {
202 printf("[%d] LOOKUP \"%s\" failed (%x) - expected %s\n",
203 op->child->line, op->fname, res, op->status);
208 static void nfs3_create(struct dbench_op *op)
212 res = nfsio_create(op->child->private, op->fname);
213 if (!check_status(res, op->status)) {
214 printf("[%d] CREATE \"%s\" failed (%x) - expected %s\n",
215 op->child->line, op->fname, res, op->status);
220 static void nfs3_write(struct dbench_op *op)
222 off_t offset = op->params[0];
223 int len = op->params[1];
224 int stable = op->params[2];
227 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
228 len = options.trunc_io;
231 res = nfsio_write(op->child->private, op->fname, rw_buf, offset, len, stable);
232 if (!check_status(res, op->status)) {
233 printf("[%d] WRITE \"%s\" failed (%x) - expected %s\n",
234 op->child->line, op->fname,
238 op->child->bytes += len;
241 static void nfs3_commit(struct dbench_op *op)
245 res = nfsio_commit(op->child->private, op->fname);
246 if (!check_status(res, op->status)) {
247 printf("[%d] COMMIT \"%s\" failed (%x) - expected %s\n",
248 op->child->line, op->fname, res, op->status);
254 static void nfs3_read(struct dbench_op *op)
256 off_t offset = op->params[0];
257 int len = op->params[1];
260 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
261 len = options.trunc_io;
264 res = nfsio_read(op->child->private, op->fname, NULL, offset, len, NULL, NULL);
265 if (!check_status(res, op->status)) {
266 printf("[%d] READ \"%s\" failed (%x) - expected %s\n",
267 op->child->line, op->fname,
271 op->child->bytes += len;
274 static void nfs3_access(struct dbench_op *op)
278 res = nfsio_access(op->child->private, op->fname, 0, NULL);
279 if (!check_status(res, op->status)) {
280 printf("[%d] ACCESS \"%s\" failed (%x) - expected %s\n",
281 op->child->line, op->fname, res, op->status);
286 static void nfs3_mkdir(struct dbench_op *op)
290 res = nfsio_mkdir(op->child->private, op->fname);
291 if (!check_status(res, op->status)) {
292 printf("[%d] MKDIR \"%s\" failed (%x) - expected %s\n",
293 op->child->line, op->fname, res, op->status);
298 static void nfs3_rmdir(struct dbench_op *op)
302 res = nfsio_rmdir(op->child->private, op->fname);
303 if (!check_status(res, op->status)) {
304 printf("[%d] RMDIR \"%s\" failed (%x) - expected %s\n",
305 op->child->line, op->fname, res, op->status);
310 static void nfs3_fsstat(struct dbench_op *op)
314 res = nfsio_fsstat(op->child->private);
315 if (!check_status(res, op->status)) {
316 printf("[%d] FSSTAT failed (%x) - expected %s\n",
317 op->child->line, res, op->status);
322 static void nfs3_fsinfo(struct dbench_op *op)
326 res = nfsio_fsinfo(op->child->private);
327 if (!check_status(res, op->status)) {
328 printf("[%d] FSINFO failed (%x) - expected %s\n",
329 op->child->line, res, op->status);
334 static void nfs3_symlink(struct dbench_op *op)
338 res = nfsio_symlink(op->child->private, op->fname, op->fname2);
339 if (!check_status(res, op->status)) {
340 printf("[%d] SYMLINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
341 op->child->line, op->fname, op->fname2,
347 static void nfs3_remove(struct dbench_op *op)
351 res = nfsio_remove(op->child->private, op->fname);
352 if (!check_status(res, op->status)) {
353 printf("[%d] REMOVE \"%s\" failed (%x) - expected %s\n",
354 op->child->line, op->fname, res, op->status);
359 static void nfs3_readdirplus(struct dbench_op *op)
363 res = nfsio_readdirplus(op->child->private, op->fname, NULL, NULL);
364 if (!check_status(res, op->status)) {
365 printf("[%d] READDIRPLUS \"%s\" failed (%x) - expected %s\n",
366 op->child->line, op->fname, res, op->status);
371 static void nfs3_link(struct dbench_op *op)
375 res = nfsio_link(op->child->private, op->fname, op->fname2);
376 if (!check_status(res, op->status)) {
377 printf("[%d] LINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
378 op->child->line, op->fname, op->fname2,
384 static void nfs3_rename(struct dbench_op *op)
388 res = nfsio_rename(op->child->private, op->fname, op->fname2);
389 if (!check_status(res, op->status)) {
390 printf("[%d] RENAME \"%s\"->\"%s\" failed (%x) - expected %s\n",
391 op->child->line, op->fname, op->fname2,
397 static int nfs3_init(void)
401 handle = nfsio_connect(options.server, options.export, options.protocol);
402 if (handle == NULL) {
403 printf("Failed to connect to NFS server\n");
407 nfsio_disconnect(handle);
411 static struct backend_op ops[] = {
412 { "Deltree", nfs3_deltree },
413 { "GETATTR3", nfs3_getattr },
414 { "LOOKUP3", nfs3_lookup },
415 { "CREATE3", nfs3_create },
416 { "WRITE3", nfs3_write },
417 { "COMMIT3", nfs3_commit },
418 { "READ3", nfs3_read },
419 { "ACCESS3", nfs3_access },
420 { "MKDIR3", nfs3_mkdir },
421 { "RMDIR3", nfs3_rmdir },
422 { "FSSTAT3", nfs3_fsstat },
423 { "FSINFO3", nfs3_fsinfo },
424 { "SYMLINK3", nfs3_symlink },
425 { "REMOVE3", nfs3_remove },
426 { "READDIRPLUS3", nfs3_readdirplus },
427 { "RENAME3", nfs3_rename },
428 { "LINK3", nfs3_link },
432 struct nb_operations nfs_ops = {
433 .backend_name = "nfsbench",
436 .cleanup = nfs3_cleanup,