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