• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
fio_gf_setup(struct thread_data * td)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 
fio_gf_cleanup(struct thread_data * td)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 
fio_gf_get_file_size(struct thread_data * td,struct fio_file * f)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 
fio_gf_open_file(struct thread_data * td,struct fio_file * f)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 
fio_gf_close_file(struct thread_data * td,struct fio_file * f)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 
fio_gf_unlink_file(struct thread_data * td,struct fio_file * f)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