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/>.
27 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
31 static char rw_buf[65536];
39 static void nfs3_deltree(struct dbench_op *op);
41 static void nfs3_cleanup(struct child_struct *child)
47 asprintf(&dname, "/clients/client%d", child->id);
54 static void nfs3_setup(struct child_struct *child)
56 const char *status = "0x00000000";
59 child->rate.last_time = timeval_current();
60 child->rate.last_bytes = 0;
63 srandom(getpid() ^ time(NULL));
64 child->private = nfsio_connect(options.server, options.export, options.protocol);
66 if (child->private == NULL) {
68 printf("nfsio_connect() failed\n");
72 /* create '/clients' */
73 res = nfsio_lookup(child->private, "/clients", NULL);
74 if (res == NFS3ERR_NOENT) {
75 res = nfsio_mkdir(child->private, "/clients");
76 if( (res != NFS3_OK) &&
77 (res != NFS3ERR_EXIST) ) {
78 printf("Failed to create '/clients' directory. res:%u\n", res);
85 static void dirent_cb(struct entryplus3 *e, void *private_data)
87 struct cb_data *cbd = private_data;
91 if (!strcmp(cbd->dirname,".")) {
94 if (!strcmp(cbd->dirname,"..")) {
98 asprintf(&objname, "%s/%s", cbd->dirname, e->name);
99 if (objname == NULL) {
100 printf("Failed to talloc ne object name in dirent_cb\n");
104 if (e->name_attributes.post_op_attr_u.attributes.type == NF3DIR) {
105 struct cb_data *new_cbd = malloc(sizeof(struct cb_data));
107 new_cbd->nfsio = cbd->nfsio;
108 new_cbd->dirname = strdup(objname);
110 nfsio_readdirplus(cbd->nfsio, objname, dirent_cb, new_cbd);
112 res = nfsio_rmdir(cbd->nfsio, objname);
113 if (res != NFS3_OK) {
114 printf("Failed to remove object : \"%s\" %s (%d)\n", objname, nfs_error(res), res);
116 free(new_cbd->dirname);
123 free(new_cbd->dirname);
128 res = nfsio_remove(cbd->nfsio, objname);
129 if (res != NFS3_OK) {
130 printf("Failed to remove object : \"%s\" %s %d\n", objname, nfs_error(res), res);
138 static void nfs3_deltree(struct dbench_op *op)
143 cbd = malloc(sizeof(struct cb_data));
145 cbd->nfsio = op->child->private;
146 cbd->dirname = discard_const(op->fname);
148 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
149 if (res != NFS3ERR_NOENT) {
150 nfsio_readdirplus(cbd->nfsio, cbd->dirname, dirent_cb, cbd);
151 nfsio_rmdir(cbd->nfsio, cbd->dirname);
154 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
155 if (res != NFS3ERR_NOENT) {
156 printf("Directory \"%s\" not empty. Aborting\n", cbd->dirname);
163 static int check_status(int status, const char *expected)
165 if (strcmp(expected, "*") == 0){
168 if (strncmp(expected, "0x", 2) == 0) {
169 return status == strtol(expected, NULL, 16);
174 static void failed(struct child_struct *child)
177 printf("ERROR: child %d failed at line %d\n", child->id, child->line);
181 static void nfs3_getattr(struct dbench_op *op)
185 res = nfsio_getattr(op->child->private, op->fname, NULL);
186 if (!check_status(res, op->status)) {
187 printf("[%d] GETATTR \"%s\" failed (%x) - expected %s\n",
188 op->child->line, op->fname, res, op->status);
194 static void nfs3_lookup(struct dbench_op *op)
198 res = nfsio_lookup(op->child->private, op->fname, NULL);
199 if (!check_status(res, op->status)) {
200 printf("[%d] LOOKUP \"%s\" failed (%x) - expected %s\n",
201 op->child->line, op->fname, res, op->status);
206 static void nfs3_create(struct dbench_op *op)
210 res = nfsio_create(op->child->private, op->fname);
211 if (!check_status(res, op->status)) {
212 printf("[%d] CREATE \"%s\" failed (%x) - expected %s\n",
213 op->child->line, op->fname, res, op->status);
218 static void nfs3_write(struct dbench_op *op)
220 int offset = op->params[0];
221 int len = op->params[1];
222 int stable = op->params[2];
225 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
226 len = options.trunc_io;
229 res = nfsio_write(op->child->private, op->fname, rw_buf, offset, len, stable);
230 if (!check_status(res, op->status)) {
231 printf("[%d] WRITE \"%s\" failed (%x) - expected %s\n",
232 op->child->line, op->fname,
236 op->child->bytes += len;
239 static void nfs3_commit(struct dbench_op *op)
243 res = nfsio_commit(op->child->private, op->fname);
244 if (!check_status(res, op->status)) {
245 printf("[%d] COMMIT \"%s\" failed (%x) - expected %s\n",
246 op->child->line, op->fname, res, op->status);
252 static void nfs3_read(struct dbench_op *op)
254 int offset = op->params[0];
255 int len = op->params[1];
258 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
259 len = options.trunc_io;
262 res = nfsio_read(op->child->private, op->fname, NULL, offset, len, NULL, NULL);
263 if (!check_status(res, op->status)) {
264 printf("[%d] READ \"%s\" failed (%x) - expected %s\n",
265 op->child->line, op->fname,
269 op->child->bytes += len;
272 static void nfs3_access(struct dbench_op *op)
276 res = nfsio_access(op->child->private, op->fname, 0, NULL);
277 if (!check_status(res, op->status)) {
278 printf("[%d] ACCESS \"%s\" failed (%x) - expected %s\n",
279 op->child->line, op->fname, res, op->status);
284 static void nfs3_mkdir(struct dbench_op *op)
288 res = nfsio_mkdir(op->child->private, op->fname);
289 if (!check_status(res, op->status)) {
290 printf("[%d] MKDIR \"%s\" failed (%x) - expected %s\n",
291 op->child->line, op->fname, res, op->status);
296 static void nfs3_rmdir(struct dbench_op *op)
300 res = nfsio_rmdir(op->child->private, op->fname);
301 if (!check_status(res, op->status)) {
302 printf("[%d] RMDIR \"%s\" failed (%x) - expected %s\n",
303 op->child->line, op->fname, res, op->status);
308 static void nfs3_fsstat(struct dbench_op *op)
312 res = nfsio_fsstat(op->child->private);
313 if (!check_status(res, op->status)) {
314 printf("[%d] FSSTAT failed (%x) - expected %s\n",
315 op->child->line, res, op->status);
320 static void nfs3_fsinfo(struct dbench_op *op)
324 res = nfsio_fsinfo(op->child->private);
325 if (!check_status(res, op->status)) {
326 printf("[%d] FSINFO failed (%x) - expected %s\n",
327 op->child->line, res, op->status);
332 static void nfs3_symlink(struct dbench_op *op)
336 res = nfsio_symlink(op->child->private, op->fname, op->fname2);
337 if (!check_status(res, op->status)) {
338 printf("[%d] SYMLINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
339 op->child->line, op->fname, op->fname2,
345 static void nfs3_remove(struct dbench_op *op)
349 res = nfsio_remove(op->child->private, op->fname);
350 if (!check_status(res, op->status)) {
351 printf("[%d] REMOVE \"%s\" failed (%x) - expected %s\n",
352 op->child->line, op->fname, res, op->status);
357 static void nfs3_readdirplus(struct dbench_op *op)
361 res = nfsio_readdirplus(op->child->private, op->fname, NULL, NULL);
362 if (!check_status(res, op->status)) {
363 printf("[%d] READDIRPLUS \"%s\" failed (%x) - expected %s\n",
364 op->child->line, op->fname, res, op->status);
369 static void nfs3_link(struct dbench_op *op)
373 res = nfsio_link(op->child->private, op->fname, op->fname2);
374 if (!check_status(res, op->status)) {
375 printf("[%d] LINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
376 op->child->line, op->fname, op->fname2,
382 static void nfs3_rename(struct dbench_op *op)
386 res = nfsio_rename(op->child->private, op->fname, op->fname2);
387 if (!check_status(res, op->status)) {
388 printf("[%d] RENAME \"%s\"->\"%s\" failed (%x) - expected %s\n",
389 op->child->line, op->fname, op->fname2,
395 static struct backend_op ops[] = {
396 { "Deltree", nfs3_deltree },
397 { "GETATTR3", nfs3_getattr },
398 { "LOOKUP3", nfs3_lookup },
399 { "CREATE3", nfs3_create },
400 { "WRITE3", nfs3_write },
401 { "COMMIT3", nfs3_commit },
402 { "READ3", nfs3_read },
403 { "ACCESS3", nfs3_access },
404 { "MKDIR3", nfs3_mkdir },
405 { "RMDIR3", nfs3_rmdir },
406 { "FSSTAT3", nfs3_fsstat },
407 { "FSINFO3", nfs3_fsinfo },
408 { "SYMLINK3", nfs3_symlink },
409 { "REMOVE3", nfs3_remove },
410 { "READDIRPLUS3", nfs3_readdirplus },
411 { "RENAME3", nfs3_rename },
412 { "LINK3", nfs3_link },
416 struct nb_operations nfs_ops = {
417 .backend_name = "nfsbench",
419 .cleanup = nfs3_cleanup,