Home | History | Annotate | Download | only in engines
      1 /*
      2  * glusterfs engine
      3  *
      4  * common Glusterfs's gfapi interface
      5  *
      6  */
      7 
      8 #include "gfapi.h"
      9 #include "../optgroup.h"
     10 
     11 struct fio_option gfapi_options[] = {
     12 	{
     13 	 .name = "volume",
     14 	 .lname = "Glusterfs volume",
     15 	 .type = FIO_OPT_STR_STORE,
     16 	 .help = "Name of the Glusterfs volume",
     17 	 .off1 = offsetof(struct gf_options, gf_vol),
     18 	 .category = FIO_OPT_C_ENGINE,
     19 	 .group = FIO_OPT_G_GFAPI,
     20 	 },
     21 	{
     22 	 .name = "brick",
     23 	 .lname = "Glusterfs brick name",
     24 	 .type = FIO_OPT_STR_STORE,
     25 	 .help = "Name of the Glusterfs brick to connect",
     26 	 .off1 = offsetof(struct gf_options, gf_brick),
     27 	 .category = FIO_OPT_C_ENGINE,
     28 	 .group = FIO_OPT_G_GFAPI,
     29 	 },
     30 	{
     31 	 .name = NULL,
     32 	 },
     33 };
     34 
     35 int fio_gf_setup(struct thread_data *td)
     36 {
     37 	int r = 0;
     38 	struct gf_data *g = NULL;
     39 	struct gf_options *opt = td->eo;
     40 	struct stat sb = { 0, };
     41 
     42 	dprint(FD_IO, "fio setup\n");
     43 
     44 	if (td->io_ops_data)
     45 		return 0;
     46 
     47 	g = malloc(sizeof(struct gf_data));
     48 	if (!g) {
     49 		log_err("malloc failed.\n");
     50 		return -ENOMEM;
     51 	}
     52 	g->fs = NULL;
     53 	g->fd = NULL;
     54 	g->aio_events = NULL;
     55 
     56 	g->fs = glfs_new(opt->gf_vol);
     57 	if (!g->fs) {
     58 		log_err("glfs_new failed.\n");
     59 		goto cleanup;
     60 	}
     61 	glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7);
     62 	/* default to tcp */
     63 	r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
     64 	if (r) {
     65 		log_err("glfs_set_volfile_server failed.\n");
     66 		goto cleanup;
     67 	}
     68 	r = glfs_init(g->fs);
     69 	if (r) {
     70 		log_err("glfs_init failed. Is glusterd running on brick?\n");
     71 		goto cleanup;
     72 	}
     73 	sleep(2);
     74 	r = glfs_lstat(g->fs, ".", &sb);
     75 	if (r) {
     76 		log_err("glfs_lstat failed.\n");
     77 		goto cleanup;
     78 	}
     79 	dprint(FD_FILE, "fio setup %p\n", g->fs);
     80 	td->io_ops_data = g;
     81 	return 0;
     82 cleanup:
     83 	if (g->fs)
     84 		glfs_fini(g->fs);
     85 	free(g);
     86 	td->io_ops_data = NULL;
     87 	return r;
     88 }
     89 
     90 void fio_gf_cleanup(struct thread_data *td)
     91 {
     92 	struct gf_data *g = td->io_ops_data;
     93 
     94 	if (g) {
     95 		if (g->aio_events)
     96 			free(g->aio_events);
     97 		if (g->fd)
     98 			glfs_close(g->fd);
     99 		if (g->fs)
    100 			glfs_fini(g->fs);
    101 		free(g);
    102 		td->io_ops_data = NULL;
    103 	}
    104 }
    105 
    106 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
    107 {
    108 	struct stat buf;
    109 	int ret;
    110 	struct gf_data *g = td->io_ops_data;
    111 
    112 	dprint(FD_FILE, "get file size %s\n", f->file_name);
    113 
    114 	if (!g || !g->fs) {
    115 		return 0;
    116 	}
    117 	if (fio_file_size_known(f))
    118 		return 0;
    119 
    120 	ret = glfs_lstat(g->fs, f->file_name, &buf);
    121 	if (ret < 0) {
    122 		log_err("glfs_lstat failed.\n");
    123 		return ret;
    124 	}
    125 
    126 	f->real_file_size = buf.st_size;
    127 	fio_file_set_size_known(f);
    128 
    129 	return 0;
    130 
    131 }
    132 
    133 int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
    134 {
    135 
    136 	int flags = 0;
    137 	int ret = 0;
    138 	struct gf_data *g = td->io_ops_data;
    139 	struct stat sb = { 0, };
    140 
    141 	if (td_write(td)) {
    142 		if (!read_only)
    143 			flags = O_RDWR;
    144 	} else if (td_read(td)) {
    145 		if (!read_only)
    146 			flags = O_RDWR;
    147 		else
    148 			flags = O_RDONLY;
    149 	}
    150 
    151 	if (td->o.odirect)
    152 		flags |= OS_O_DIRECT;
    153 	if (td->o.sync_io)
    154 		flags |= O_SYNC;
    155 
    156 	dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
    157 	       flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
    158 	g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
    159 	if (!g->fd) {
    160 		ret = errno;
    161 		log_err("glfs_creat failed.\n");
    162 		return ret;
    163 	}
    164 	/* file for read doesn't exist or shorter than required, create/extend it */
    165 	if (td_read(td)) {
    166 		if (glfs_lstat(g->fs, f->file_name, &sb)
    167 		    || sb.st_size < f->real_file_size) {
    168 			dprint(FD_FILE, "fio extend file %s from %ld to %ld\n",
    169 			       f->file_name, sb.st_size, f->real_file_size);
    170 			ret = glfs_ftruncate(g->fd, f->real_file_size);
    171 			if (ret) {
    172 				log_err("failed fio extend file %s to %ld\n",
    173 					f->file_name, f->real_file_size);
    174 			} else {
    175 				unsigned long long left;
    176 				unsigned int bs;
    177 				char *b;
    178 				int r;
    179 
    180 				/* fill the file, copied from extend_file */
    181 				b = malloc(td->o.max_bs[DDIR_WRITE]);
    182 
    183 				left = f->real_file_size;
    184 				while (left && !td->terminate) {
    185 					bs = td->o.max_bs[DDIR_WRITE];
    186 					if (bs > left)
    187 						bs = left;
    188 
    189 					fill_io_buffer(td, b, bs, bs);
    190 
    191 					r = glfs_write(g->fd, b, bs, 0);
    192 					dprint(FD_IO,
    193 					       "fio write %d of %ld file %s\n",
    194 					       r, f->real_file_size,
    195 					       f->file_name);
    196 
    197 					if (r > 0) {
    198 						left -= r;
    199 						continue;
    200 					} else {
    201 						if (r < 0) {
    202 							int __e = errno;
    203 
    204 							if (__e == ENOSPC) {
    205 								if (td->o.
    206 								    fill_device)
    207 									break;
    208 								log_info
    209 								    ("fio: ENOSPC on laying out "
    210 								     "file, stopping\n");
    211 								break;
    212 							}
    213 							td_verror(td, errno,
    214 								  "write");
    215 						} else
    216 							td_verror(td, EIO,
    217 								  "write");
    218 
    219 						break;
    220 					}
    221 				}
    222 
    223 				if (b)
    224 					free(b);
    225 				glfs_lseek(g->fd, 0, SEEK_SET);
    226 
    227 				if (td->terminate && td->o.unlink) {
    228 					dprint(FD_FILE, "terminate unlink %s\n",
    229 					       f->file_name);
    230 					glfs_unlink(g->fs, f->file_name);
    231 				} else if (td->o.create_fsync) {
    232 					if (glfs_fsync(g->fd) < 0) {
    233 						dprint(FD_FILE,
    234 						       "failed to sync, close %s\n",
    235 						       f->file_name);
    236 						td_verror(td, errno, "fsync");
    237 						glfs_close(g->fd);
    238 						g->fd = NULL;
    239 						return 1;
    240 					}
    241 				}
    242 			}
    243 		}
    244 	}
    245 #if defined(GFAPI_USE_FADVISE)
    246 	{
    247 		int r = 0;
    248 		if (td_random(td)) {
    249 			r = glfs_fadvise(g->fd, 0, f->real_file_size,
    250 					 POSIX_FADV_RANDOM);
    251 		} else {
    252 			r = glfs_fadvise(g->fd, 0, f->real_file_size,
    253 					 POSIX_FADV_SEQUENTIAL);
    254 		}
    255 		if (r) {
    256 			dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
    257 			       f->file_name, r);
    258 		}
    259 	}
    260 #endif
    261 	dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
    262 	f->fd = -1;
    263 	f->shadow_fd = -1;
    264 	td->o.open_files ++;
    265 	return ret;
    266 }
    267 
    268 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
    269 {
    270 	int ret = 0;
    271 	struct gf_data *g = td->io_ops_data;
    272 
    273 	dprint(FD_FILE, "fd close %s\n", f->file_name);
    274 
    275 	if (g) {
    276 		if (g->fd && glfs_close(g->fd) < 0)
    277 			ret = errno;
    278 		g->fd = NULL;
    279 	}
    280 
    281 	return ret;
    282 }
    283 
    284 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
    285 {
    286 	int ret = 0;
    287 	struct gf_data *g = td->io_ops_data;
    288 
    289 	dprint(FD_FILE, "fd unlink %s\n", f->file_name);
    290 
    291 	if (g) {
    292 		if (g->fd && glfs_close(g->fd) < 0)
    293 			ret = errno;
    294 
    295 		glfs_unlink(g->fs, f->file_name);
    296 
    297 		if (g->fs)
    298 			glfs_fini(g->fs);
    299 
    300 		g->fd = NULL;
    301 		free(g);
    302 	}
    303 	td->io_ops_data = NULL;
    304 
    305 	return ret;
    306 }
    307