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
28 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
37 static void nfs3_deltree(struct dbench_op *op);
39 static void nfs3_cleanup(struct child_struct *child)
45 asprintf(&dname, "/clients/client%d", child->id);
52 static void nfs3_setup(struct child_struct *child)
54 const char *status = "0x00000000";
57 child->rate.last_time = timeval_current();
58 child->rate.last_bytes = 0;
60 srandom(getpid() ^ time(NULL));
61 child->private = nfsio_connect(options.server, options.export, options.protocol, global_random + child->id, child->num_clients);
62 if (child->private == NULL) {
64 printf("nfsio_connect() failed\n");
68 /* create '/clients' */
69 res = nfsio_lookup(child->private, "/clients", NULL);
70 if (res == NFS3ERR_NOENT) {
71 res = nfsio_mkdir(child->private, "/clients");
72 if( (res != NFS3_OK) &&
73 (res != NFS3ERR_EXIST) ) {
74 printf("Failed to create '/clients' directory. res:%u\n", res);
81 static void dirent_cb(struct entryplus3 *e, void *private_data)
83 struct cb_data *cbd = private_data;
87 if (!strcmp(cbd->dirname,".")) {
90 if (!strcmp(cbd->dirname,"..")) {
94 asprintf(&objname, "%s/%s", cbd->dirname, e->name);
95 if (objname == NULL) {
96 printf("Failed to talloc ne object name in dirent_cb\n");
100 if (e->name_attributes.post_op_attr_u.attributes.type == NF3DIR) {
101 struct cb_data *new_cbd = malloc(sizeof(struct cb_data));
103 new_cbd->nfsio = cbd->nfsio;
104 new_cbd->dirname = strdup(objname);
106 nfsio_readdirplus(cbd->nfsio, objname, dirent_cb, new_cbd);
108 res = nfsio_rmdir(cbd->nfsio, objname);
109 if (res != NFS3_OK) {
110 printf("Failed to remove object : \"%s\" %s (%d)\n", objname, nfs_error(res), res);
112 free(new_cbd->dirname);
119 free(new_cbd->dirname);
124 res = nfsio_remove(cbd->nfsio, objname);
125 if (res != NFS3_OK) {
126 printf("Failed to remove object : \"%s\" %s %d\n", objname, nfs_error(res), res);
134 static void nfs3_deltree(struct dbench_op *op)
139 cbd = malloc(sizeof(struct cb_data));
141 cbd->nfsio = op->child->private;
142 cbd->dirname = discard_const(op->fname);
144 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
145 if (res != NFS3ERR_NOENT) {
146 nfsio_readdirplus(cbd->nfsio, cbd->dirname, dirent_cb, cbd);
147 nfsio_rmdir(cbd->nfsio, cbd->dirname);
150 res = nfsio_lookup(cbd->nfsio, cbd->dirname, NULL);
151 if (res != NFS3ERR_NOENT) {
152 printf("Directory \"%s\" not empty. Aborting\n", cbd->dirname);
159 static int check_status(int status, const char *expected)
161 if (strcmp(expected, "*") == 0){
164 if (strncmp(expected, "0x", 2) == 0) {
165 return status == strtol(expected, NULL, 16);
170 static void failed(struct child_struct *child)
173 printf("ERROR: child %d failed at line %d\n", child->id, child->line);
177 static void nfs3_getattr(struct dbench_op *op)
181 res = nfsio_getattr(op->child->private, op->fname, NULL);
182 if (!check_status(res, op->status)) {
183 printf("[%d] GETATTR \"%s\" failed (%x) - expected %s\n",
184 op->child->line, op->fname, res, op->status);
190 static void nfs3_lookup(struct dbench_op *op)
194 res = nfsio_lookup(op->child->private, op->fname, NULL);
195 if (!check_status(res, op->status)) {
196 printf("[%d] LOOKUP \"%s\" failed (%x) - expected %s\n",
197 op->child->line, op->fname, res, op->status);
202 static void nfs3_create(struct dbench_op *op)
206 res = nfsio_create(op->child->private, op->fname);
207 if (!check_status(res, op->status)) {
208 printf("[%d] CREATE \"%s\" failed (%x) - expected %s\n",
209 op->child->line, op->fname, res, op->status);
214 static void nfs3_write(struct dbench_op *op)
216 off_t offset = op->params[0];
217 int len = op->params[1];
218 int stable = op->params[2];
221 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
222 len = options.trunc_io;
225 res = nfsio_write(op->child->private, op->fname, rw_buf, offset, len, stable);
226 if (!check_status(res, op->status)) {
227 printf("[%d] WRITE \"%s\" failed (%x) - expected %s\n",
228 op->child->line, op->fname,
232 op->child->bytes += len;
235 static void nfs3_commit(struct dbench_op *op)
239 res = nfsio_commit(op->child->private, op->fname);
240 if (!check_status(res, op->status)) {
241 printf("[%d] COMMIT \"%s\" failed (%x) - expected %s\n",
242 op->child->line, op->fname, res, op->status);
248 static void nfs3_read(struct dbench_op *op)
250 off_t offset = op->params[0];
251 int len = op->params[1];
254 if ((options.trunc_io > 0) && (len > options.trunc_io)) {
255 len = options.trunc_io;
258 res = nfsio_read(op->child->private, op->fname, NULL, offset, len, NULL, NULL);
259 if (!check_status(res, op->status)) {
260 printf("[%d] READ \"%s\" failed (%x) - expected %s\n",
261 op->child->line, op->fname,
265 op->child->bytes += len;
268 static void nfs3_access(struct dbench_op *op)
272 res = nfsio_access(op->child->private, op->fname, 0, NULL);
273 if (!check_status(res, op->status)) {
274 printf("[%d] ACCESS \"%s\" failed (%x) - expected %s\n",
275 op->child->line, op->fname, res, op->status);
280 static void nfs3_mkdir(struct dbench_op *op)
284 res = nfsio_mkdir(op->child->private, op->fname);
285 if (!check_status(res, op->status)) {
286 printf("[%d] MKDIR \"%s\" failed (%x) - expected %s\n",
287 op->child->line, op->fname, res, op->status);
292 static void nfs3_rmdir(struct dbench_op *op)
296 res = nfsio_rmdir(op->child->private, op->fname);
297 if (!check_status(res, op->status)) {
298 printf("[%d] RMDIR \"%s\" failed (%x) - expected %s\n",
299 op->child->line, op->fname, res, op->status);
304 static void nfs3_fsstat(struct dbench_op *op)
308 res = nfsio_fsstat(op->child->private);
309 if (!check_status(res, op->status)) {
310 printf("[%d] FSSTAT failed (%x) - expected %s\n",
311 op->child->line, res, op->status);
316 static void nfs3_fsinfo(struct dbench_op *op)
320 res = nfsio_fsinfo(op->child->private);
321 if (!check_status(res, op->status)) {
322 printf("[%d] FSINFO failed (%x) - expected %s\n",
323 op->child->line, res, op->status);
328 static void nfs3_symlink(struct dbench_op *op)
332 res = nfsio_symlink(op->child->private, op->fname, op->fname2);
333 if (!check_status(res, op->status)) {
334 printf("[%d] SYMLINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
335 op->child->line, op->fname, op->fname2,
341 static void nfs3_remove(struct dbench_op *op)
345 res = nfsio_remove(op->child->private, op->fname);
346 if (!check_status(res, op->status)) {
347 printf("[%d] REMOVE \"%s\" failed (%x) - expected %s\n",
348 op->child->line, op->fname, res, op->status);
353 static void nfs3_readdirplus(struct dbench_op *op)
357 res = nfsio_readdirplus(op->child->private, op->fname, NULL, NULL);
358 if (!check_status(res, op->status)) {
359 printf("[%d] READDIRPLUS \"%s\" failed (%x) - expected %s\n",
360 op->child->line, op->fname, res, op->status);
365 static void nfs3_link(struct dbench_op *op)
369 res = nfsio_link(op->child->private, op->fname, op->fname2);
370 if (!check_status(res, op->status)) {
371 printf("[%d] LINK \"%s\"->\"%s\" failed (%x) - expected %s\n",
372 op->child->line, op->fname, op->fname2,
378 static void nfs3_rename(struct dbench_op *op)
382 res = nfsio_rename(op->child->private, op->fname, op->fname2);
383 if (!check_status(res, op->status)) {
384 printf("[%d] RENAME \"%s\"->\"%s\" failed (%x) - expected %s\n",
385 op->child->line, op->fname, op->fname2,
391 static int nfs3_init(void)
395 handle = nfsio_connect(options.server, options.export, options.protocol, global_random, 1);
396 if (handle == NULL) {
397 printf("Failed to connect to NFS server\n");
401 nfsio_disconnect(handle);
405 static struct backend_op ops[] = {
406 { "Deltree", nfs3_deltree },
407 { "GETATTR3", nfs3_getattr },
408 { "LOOKUP3", nfs3_lookup },
409 { "CREATE3", nfs3_create },
410 { "WRITE3", nfs3_write },
411 { "COMMIT3", nfs3_commit },
412 { "READ3", nfs3_read },
413 { "ACCESS3", nfs3_access },
414 { "MKDIR3", nfs3_mkdir },
415 { "RMDIR3", nfs3_rmdir },
416 { "FSSTAT3", nfs3_fsstat },
417 { "FSINFO3", nfs3_fsinfo },
418 { "SYMLINK3", nfs3_symlink },
419 { "REMOVE3", nfs3_remove },
420 { "READDIRPLUS3", nfs3_readdirplus },
421 { "RENAME3", nfs3_rename },
422 { "LINK3", nfs3_link },
426 struct nb_operations nfs_ops = {
427 .backend_name = "nfsbench",
430 .cleanup = nfs3_cleanup,