#include "dbench.h"
#include <zlib.h>
-#define ival(s) strtol(s, NULL, 0)
+#define ival(s) strtoll(s, NULL, 0)
static void nb_sleep(int usec)
{
#define OP_LATENCY(opname) finish_op(child, &child->op.op_ ## opname)
+/* here we parse "special" arguments that start with '*'
+ * '*' itself means a random 64 bit number, but this can be qualified as
+ *
+ * '*' a random 64 bit number
+ * '...%y' modulo y
+ * '.../y' align the number as an integer multiple of y (( x = (x/y)*y))
+ * '...+y' add 'y'
+ *
+ * Examples :
+ * '*' : random 64 bit number
+ * '*%1024' : random number between 0 and 1023
+ * '* /1024' : random 64 bit number aligned to n*1024
+ * '*%1024/2 : random even number between 0 and 1023
+ */
+uint64_t parse_special(const char *fmt)
+{
+ char q;
+ uint64_t num;
+ uint64_t val;
+
+ num = random();
+ num = (num <<32) | random();
+
+ fmt++;
+ while (*fmt != '\0') {
+ q = *fmt++;
+ val = strtoll(fmt, NULL, 0);
+ if (val == 0) {
+ printf("Illegal value in random number qualifier. Can not be zero\n");
+ return num;
+ }
+
+ switch (q) {
+ case '/':
+ num = (num/val)*val;
+ break;
+ case '%':
+ num = num%val;
+ break;
+ case '+':
+ num = num+val;
+ break;
+ default:
+ printf("Unknown qualifier '%c' for randum number qualifier\n", q);
+ }
+
+ /* skip until the next token */
+ while (*fmt != '\0') {
+ switch (*fmt) {
+ case '0'...'9':
+ case 'a'...'f':
+ case 'A'...'F':
+ case 'x':
+ case 'X':
+ fmt++;
+ continue;
+ }
+ break;
+ }
+ }
+
+ return num;
+}
/*
one child operation
*/
op.fname2 = fname2;
op.status = status;
for (i=0;i<sizeof(op.params)/sizeof(op.params[0]);i++) {
- if (!strcmp(params[i], "*")) {
- op.params[i] = random();
+ if (params[i][0] == '*') {
+ op.params[i] = parse_special(params[i]);
} else {
op.params[i] = params[i]?ival(params[i]):0;
}
const char *fname;
const char *fname2;
const char *status;
- int params[10];
+ int64_t params[10];
};
struct backend_op {
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
+#include <arpa/inet.h>
#include "dbench.h"
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
+#define _FILE_OFFSET_BITS 64
#include "mount.h"
#include "nfs.h"
#include "libnfs.h"
typedef struct _tree_t {
data_t key;
data_t fh;
- ssize_t size;
+ off_t file_size;
struct _tree_t *parent;
struct _tree_t *left;
struct _tree_t *right;
return ;
}
-static data_t *lookup_fhandle(struct nfsio *nfsio, const char *name, ssize_t *size)
+static data_t *lookup_fhandle(struct nfsio *nfsio, const char *name, off_t *off)
{
tree_t *t;
return recursive_lookup_fhandle(nfsio, name);
}
- if (size) {
- *size = t->size;
+ if (off) {
+ *off = t->file_size;
}
return &t->fh;
return;
}
-static void insert_fhandle(struct nfsio *nfsio, const char *name, const char *fhandle, int length, ssize_t size)
+static void insert_fhandle(struct nfsio *nfsio, const char *name, const char *fhandle, int length, off_t off)
{
tree_t *tmp_t;
tree_t *t;
memcpy(discard_const(t->fh.dptr), fhandle, length);
t->fh.dsize = length;
- t->size = size;
-
+ t->file_size = off;
t->left = NULL;
t->right = NULL;
t->parent = NULL;
return ret;
}
-nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int *count, int *eof)
+nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint64_t offset, int len, int *count, int *eof)
{
struct READ3args READ3args;
struct READ3res *READ3res;
int ret = NFS3_OK;
data_t *fh;
- ssize_t size;
+ off_t size;
fh = lookup_fhandle(nfsio, name, &size);
if (fh == NULL) {
nfsstat3 nfsio_remove(struct nfsio *nfsio, const char *name);
nfsstat3 nfsio_write(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int stable);
nfsstat3 nfsio_commit(struct nfsio *nfsio, const char *name);
-nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int *count, int *eof);
+nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint64_t offset, int len, int *count, int *eof);
nfsstat3 nfsio_fsinfo(struct nfsio *nfsio);
nfsstat3 nfsio_fsstat(struct nfsio *nfsio);
nfsstat3 nfsio_pathconf(struct nfsio *nfsio, char *name);
+# The READ3 command takes an offset. This can be specified eitehr as an absolute
+# number, but also as a simple expression for generation of random I/O
+#
+# Offset is then a string starting with a '*' followed by one or more
+# qualifier :
+# '*' : Random 64 bit integer
+# '/yyy' : align the number to yyy. This is the same as x = (x/y)*y
+# '%yyy' : modulo yyy. This si teh same as x = x%y
+# '+yyy' : Add y
+#
+# Examples :
+# '*' A random offset between 0 and 2**64-1
+# '*/0x1000' A random offset aligned to a page boundary (4096)
+# '*/0x1000%5000000' A random offset between 0 and 500000 aligned to page
+# boundary
+#
+# '*%100+25' A random offset between 25 and 124
+#
+#
+#
+#
# DELTREE if we want to delete the client directory everytime we restart
# the script. Remove these two lines if the script is only "read-only"
# reading from pre-existing files in the /clients/clientX/ tree
0.000 Deltree "/clients/client1" 0x00000000
#
+#
+#
# Make sure these directories exist. We specify * as the status code
# since these directories might already exist and in which case
# we dont care that the command returned an error.
+#
+#
+# MKDIR3 <path> <status>
0.000 MKDIR3 "/clients" *
0.000 MKDIR3 "/clients/client1" *
#
+#
+#
# This lookup must be performed to pre-load the name to filehandle cache.
# Othervise we will get errors like this :
# failed to fetch handle in nfsio_read
#
+# LOOKUP3 <path> <status>
0.000 LOOKUP3 "/clients/client1" 0x00000000
#
+#
+#
# Here is where the script starts
#
+# GETATTR3 <path> <status>
0.010 GETATTR3 "/clients/client1" 0x00000000
0.020 GETATTR3 "/clients/client1" 0x00000000
0.030 GETATTR3 "/clients/client1" 0x00000000
0.040 CREATE3 "/clients/client1/test.file" 0x00000000
0.050 CREATE3 "/clients/client1/tmp.file" 0x00000000
+#
+#
+#
+# WRITE3 <path> <offset> <size> <status>
+#
# second last argument to WRITE is the "stable' field.
# 0 : UNSTABLE (default for NFS)
# 1 : DATA STABLE
1.010 WRITE3 "/clients/client1/test.file" 1024 1024 0 0x00000000
1.020 WRITE3 "/clients/client1/test.file" 2048 2048 0 0x00000000
1.030 COMMIT3 "/clients/client1/test.file" 0x00000000
+#
+#
+#
+# READ <path> <offset> <size> <status>
1.040 READ3 "/clients/client1/test.file" 2048 2048 0x00000000
+#
+#
+#
+#
1.050 LOOKUP3 "/clients/client1/test.file" 0x00000000
1.060 LINK3 "/clients/client1/hard.link" "/clients/client1/test.file" 0x00000000
1.070 REMOVE3 "/clients/client1/hard.link" 0x00000000
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#define _FILE_OFFSET_BITS 64
+
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
static void nfs3_write(struct dbench_op *op)
{
- int offset = op->params[0];
+ off_t offset = op->params[0];
int len = op->params[1];
int stable = op->params[2];
nfsstat3 res;
static void nfs3_read(struct dbench_op *op)
{
- int offset = op->params[0];
+ off_t offset = op->params[0];
int len = op->params[1];
nfsstat3 res = 0;