Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Wrap GlusterFS GFAPI calls in vfs functions.
5 :
6 : Copyright (c) 2013 Anand Avati <avati@redhat.com>
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : /**
23 : * @file vfs_glusterfs.c
24 : * @author Anand Avati <avati@redhat.com>
25 : * @date May 2013
26 : * @brief Samba VFS module for glusterfs
27 : *
28 : * @todo
29 : * - sendfile/recvfile support
30 : *
31 : * A Samba VFS module for GlusterFS, based on Gluster's libgfapi.
32 : * This is a "bottom" vfs module (not something to be stacked on top of
33 : * another module), and translates (most) calls to the closest actions
34 : * available in libgfapi.
35 : *
36 : */
37 :
38 : #include "includes.h"
39 : #include "smbd/smbd.h"
40 : #include <stdio.h>
41 : #include <glusterfs/api/glfs.h>
42 : #include "lib/util/dlinklist.h"
43 : #include "lib/util/tevent_unix.h"
44 : #include "smbd/globals.h"
45 : #include "lib/util/sys_rw.h"
46 : #include "smbprofile.h"
47 : #include "modules/posixacl_xattr.h"
48 : #include "lib/pthreadpool/pthreadpool_tevent.h"
49 :
50 : #define DEFAULT_VOLFILE_SERVER "localhost"
51 : #define GLUSTER_NAME_MAX 255
52 :
53 : /**
54 : * Helper to convert struct stat to struct stat_ex.
55 : */
56 0 : static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src)
57 : {
58 0 : ZERO_STRUCTP(dst);
59 :
60 0 : dst->st_ex_dev = src->st_dev;
61 0 : dst->st_ex_ino = src->st_ino;
62 0 : dst->st_ex_mode = src->st_mode;
63 0 : dst->st_ex_nlink = src->st_nlink;
64 0 : dst->st_ex_uid = src->st_uid;
65 0 : dst->st_ex_gid = src->st_gid;
66 0 : dst->st_ex_rdev = src->st_rdev;
67 0 : dst->st_ex_size = src->st_size;
68 0 : dst->st_ex_atime.tv_sec = src->st_atime;
69 0 : dst->st_ex_mtime.tv_sec = src->st_mtime;
70 0 : dst->st_ex_ctime.tv_sec = src->st_ctime;
71 0 : dst->st_ex_btime.tv_sec = src->st_mtime;
72 0 : dst->st_ex_blksize = src->st_blksize;
73 0 : dst->st_ex_blocks = src->st_blocks;
74 : #ifdef STAT_HAVE_NSEC
75 : dst->st_ex_atime.tv_nsec = src->st_atime_nsec;
76 : dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec;
77 : dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec;
78 : dst->st_ex_btime.tv_nsec = src->st_mtime_nsec;
79 : #endif
80 0 : }
81 :
82 : /* pre-opened glfs_t */
83 :
84 : static struct glfs_preopened {
85 : char *volume;
86 : char *connectpath;
87 : glfs_t *fs;
88 : int ref;
89 : struct glfs_preopened *next, *prev;
90 : } *glfs_preopened;
91 :
92 :
93 0 : static int glfs_set_preopened(const char *volume, const char *connectpath, glfs_t *fs)
94 : {
95 0 : struct glfs_preopened *entry = NULL;
96 :
97 0 : entry = talloc_zero(NULL, struct glfs_preopened);
98 0 : if (!entry) {
99 0 : errno = ENOMEM;
100 0 : return -1;
101 : }
102 :
103 0 : entry->volume = talloc_strdup(entry, volume);
104 0 : if (!entry->volume) {
105 0 : talloc_free(entry);
106 0 : errno = ENOMEM;
107 0 : return -1;
108 : }
109 :
110 0 : entry->connectpath = talloc_strdup(entry, connectpath);
111 0 : if (entry->connectpath == NULL) {
112 0 : talloc_free(entry);
113 0 : errno = ENOMEM;
114 0 : return -1;
115 : }
116 :
117 0 : entry->fs = fs;
118 0 : entry->ref = 1;
119 :
120 0 : DLIST_ADD(glfs_preopened, entry);
121 :
122 0 : return 0;
123 : }
124 :
125 0 : static glfs_t *glfs_find_preopened(const char *volume, const char *connectpath)
126 : {
127 0 : struct glfs_preopened *entry = NULL;
128 :
129 0 : for (entry = glfs_preopened; entry; entry = entry->next) {
130 0 : if (strcmp(entry->volume, volume) == 0 &&
131 0 : strcmp(entry->connectpath, connectpath) == 0)
132 : {
133 0 : entry->ref++;
134 0 : return entry->fs;
135 : }
136 : }
137 :
138 0 : return NULL;
139 : }
140 :
141 0 : static void glfs_clear_preopened(glfs_t *fs)
142 : {
143 0 : struct glfs_preopened *entry = NULL;
144 :
145 0 : for (entry = glfs_preopened; entry; entry = entry->next) {
146 0 : if (entry->fs == fs) {
147 0 : if (--entry->ref)
148 0 : return;
149 :
150 0 : DLIST_REMOVE(glfs_preopened, entry);
151 :
152 0 : glfs_fini(entry->fs);
153 0 : talloc_free(entry);
154 : }
155 : }
156 : }
157 :
158 0 : static int vfs_gluster_set_volfile_servers(glfs_t *fs,
159 : const char *volfile_servers)
160 : {
161 0 : char *server = NULL;
162 0 : size_t server_count = 0;
163 0 : size_t server_success = 0;
164 0 : int ret = -1;
165 0 : TALLOC_CTX *frame = talloc_stackframe();
166 :
167 0 : DBG_INFO("servers list %s\n", volfile_servers);
168 :
169 0 : while (next_token_talloc(frame, &volfile_servers, &server, " \t")) {
170 0 : char *transport = NULL;
171 0 : char *host = NULL;
172 0 : int port = 0;
173 :
174 0 : server_count++;
175 0 : DBG_INFO("server %zu %s\n", server_count, server);
176 :
177 : /* Determine the transport type */
178 0 : if (strncmp(server, "unix+", 5) == 0) {
179 0 : port = 0;
180 0 : transport = talloc_strdup(frame, "unix");
181 0 : if (!transport) {
182 0 : errno = ENOMEM;
183 0 : goto out;
184 : }
185 0 : host = talloc_strdup(frame, server + 5);
186 0 : if (!host) {
187 0 : errno = ENOMEM;
188 0 : goto out;
189 : }
190 : } else {
191 0 : char *p = NULL;
192 0 : char *port_index = NULL;
193 :
194 0 : if (strncmp(server, "tcp+", 4) == 0) {
195 0 : server += 4;
196 : }
197 :
198 : /* IPv6 is enclosed in []
199 : * ':' before ']' is part of IPv6
200 : * ':' after ']' indicates port
201 : */
202 0 : p = server;
203 0 : if (server[0] == '[') {
204 0 : server++;
205 0 : p = index(server, ']');
206 0 : if (p == NULL) {
207 : /* Malformed IPv6 */
208 0 : continue;
209 : }
210 0 : p[0] = '\0';
211 0 : p++;
212 : }
213 :
214 0 : port_index = index(p, ':');
215 :
216 0 : if (port_index == NULL) {
217 0 : port = 0;
218 : } else {
219 0 : port = atoi(port_index + 1);
220 0 : port_index[0] = '\0';
221 : }
222 0 : transport = talloc_strdup(frame, "tcp");
223 0 : if (!transport) {
224 0 : errno = ENOMEM;
225 0 : goto out;
226 : }
227 0 : host = talloc_strdup(frame, server);
228 0 : if (!host) {
229 0 : errno = ENOMEM;
230 0 : goto out;
231 : }
232 : }
233 :
234 0 : DBG_INFO("Calling set volfile server with params "
235 : "transport=%s, host=%s, port=%d\n", transport,
236 : host, port);
237 :
238 0 : ret = glfs_set_volfile_server(fs, transport, host, port);
239 0 : if (ret < 0) {
240 0 : DBG_WARNING("Failed to set volfile_server "
241 : "transport=%s, host=%s, port=%d (%s)\n",
242 : transport, host, port, strerror(errno));
243 : } else {
244 0 : server_success++;
245 : }
246 : }
247 :
248 0 : out:
249 0 : if (server_count == 0) {
250 0 : ret = -1;
251 0 : } else if (server_success < server_count) {
252 0 : DBG_WARNING("Failed to set %zu out of %zu servers parsed\n",
253 : server_count - server_success, server_count);
254 0 : ret = 0;
255 : }
256 :
257 0 : TALLOC_FREE(frame);
258 0 : return ret;
259 : }
260 :
261 : /* Disk Operations */
262 :
263 0 : static int check_for_write_behind_translator(TALLOC_CTX *mem_ctx,
264 : glfs_t *fs,
265 : const char *volume)
266 : {
267 0 : char *buf = NULL;
268 0 : char **lines = NULL;
269 0 : int numlines = 0;
270 : int i;
271 : char *option;
272 0 : bool write_behind_present = false;
273 : size_t newlen;
274 : int ret;
275 :
276 0 : ret = glfs_get_volfile(fs, NULL, 0);
277 0 : if (ret == 0) {
278 0 : DBG_ERR("%s: Failed to get volfile for "
279 : "volume (%s): No volfile\n",
280 : volume,
281 : strerror(errno));
282 0 : return -1;
283 : }
284 0 : if (ret > 0) {
285 0 : DBG_ERR("%s: Invalid return %d for glfs_get_volfile for "
286 : "volume (%s): No volfile\n",
287 : volume,
288 : ret,
289 : strerror(errno));
290 0 : return -1;
291 : }
292 :
293 0 : newlen = 0 - ret;
294 :
295 0 : buf = talloc_zero_array(mem_ctx, char, newlen);
296 0 : if (buf == NULL) {
297 0 : return -1;
298 : }
299 :
300 0 : ret = glfs_get_volfile(fs, buf, newlen);
301 0 : if (ret != newlen) {
302 0 : TALLOC_FREE(buf);
303 0 : DBG_ERR("%s: Failed to get volfile for volume (%s)\n",
304 : volume, strerror(errno));
305 0 : return -1;
306 : }
307 :
308 0 : option = talloc_asprintf(mem_ctx, "volume %s-write-behind", volume);
309 0 : if (option == NULL) {
310 0 : TALLOC_FREE(buf);
311 0 : return -1;
312 : }
313 :
314 : /*
315 : * file_lines_parse() plays horrible tricks with
316 : * the passed-in talloc pointers and the hierarcy
317 : * which makes freeing hard to get right.
318 : *
319 : * As we know mem_ctx is freed by the caller, after
320 : * this point don't free on exit and let the caller
321 : * handle it. This violates good Samba coding practice
322 : * but we know we're not leaking here.
323 : */
324 :
325 0 : lines = file_lines_parse(buf,
326 : newlen,
327 : &numlines,
328 : mem_ctx);
329 0 : if (lines == NULL || numlines <= 0) {
330 0 : return -1;
331 : }
332 : /* On success, buf is now a talloc child of lines !! */
333 :
334 0 : for (i=0; i < numlines; i++) {
335 0 : if (strequal(lines[i], option)) {
336 0 : write_behind_present = true;
337 0 : break;
338 : }
339 : }
340 :
341 0 : if (write_behind_present) {
342 0 : DBG_ERR("Write behind translator is enabled for "
343 : "volume (%s), refusing to connect! "
344 : "Please turn off the write behind translator by calling "
345 : "'gluster volume set %s performance.write-behind off' "
346 : "on the commandline. "
347 : "Check the vfs_glusterfs(8) manpage for "
348 : "further details.\n",
349 : volume, volume);
350 0 : return -1;
351 : }
352 :
353 0 : return 0;
354 : }
355 :
356 0 : static int vfs_gluster_connect(struct vfs_handle_struct *handle,
357 : const char *service,
358 : const char *user)
359 : {
360 0 : const struct loadparm_substitution *lp_sub =
361 : loadparm_s3_global_substitution();
362 : const char *volfile_servers;
363 : const char *volume;
364 : char *logfile;
365 : int loglevel;
366 0 : glfs_t *fs = NULL;
367 : TALLOC_CTX *tmp_ctx;
368 0 : int ret = 0;
369 0 : bool write_behind_pass_through_set = false;
370 :
371 0 : tmp_ctx = talloc_new(NULL);
372 0 : if (tmp_ctx == NULL) {
373 0 : ret = -1;
374 0 : goto done;
375 : }
376 0 : logfile = lp_parm_substituted_string(tmp_ctx,
377 : lp_sub,
378 0 : SNUM(handle->conn),
379 : "glusterfs",
380 : "logfile",
381 : NULL);
382 :
383 0 : loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1);
384 :
385 0 : volfile_servers = lp_parm_substituted_string(tmp_ctx,
386 : lp_sub,
387 0 : SNUM(handle->conn),
388 : "glusterfs",
389 : "volfile_server",
390 : NULL);
391 0 : if (volfile_servers == NULL) {
392 0 : volfile_servers = DEFAULT_VOLFILE_SERVER;
393 : }
394 :
395 0 : volume = lp_parm_const_string(SNUM(handle->conn), "glusterfs", "volume",
396 : NULL);
397 0 : if (volume == NULL) {
398 0 : volume = service;
399 : }
400 :
401 0 : fs = glfs_find_preopened(volume, handle->conn->connectpath);
402 0 : if (fs) {
403 0 : goto done;
404 : }
405 :
406 0 : fs = glfs_new(volume);
407 0 : if (fs == NULL) {
408 0 : ret = -1;
409 0 : goto done;
410 : }
411 :
412 0 : ret = vfs_gluster_set_volfile_servers(fs, volfile_servers);
413 0 : if (ret < 0) {
414 0 : DBG_ERR("Failed to set volfile_servers from list %s\n",
415 : volfile_servers);
416 0 : goto done;
417 : }
418 :
419 0 : ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl",
420 : "true");
421 0 : if (ret < 0) {
422 0 : DEBUG(0, ("%s: Failed to set xlator options\n", volume));
423 0 : goto done;
424 : }
425 :
426 0 : ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-selinux",
427 : "true");
428 0 : if (ret < 0) {
429 0 : DEBUG(0, ("%s: Failed to set xlator options\n", volume));
430 0 : goto done;
431 : }
432 :
433 0 : ret = glfs_set_xlator_option(fs, "*-snapview-client",
434 : "snapdir-entry-path",
435 0 : handle->conn->connectpath);
436 0 : if (ret < 0) {
437 0 : DEBUG(0, ("%s: Failed to set xlator option:"
438 : " snapdir-entry-path\n", volume));
439 0 : goto done;
440 : }
441 :
442 : #ifdef HAVE_GFAPI_VER_7_9
443 : ret = glfs_set_xlator_option(fs, "*-write-behind", "pass-through",
444 : "true");
445 : if (ret < 0) {
446 : DBG_ERR("%s: Failed to set xlator option: pass-through\n",
447 : volume);
448 : goto done;
449 : }
450 : write_behind_pass_through_set = true;
451 : #endif
452 :
453 0 : ret = glfs_set_logging(fs, logfile, loglevel);
454 0 : if (ret < 0) {
455 0 : DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n",
456 : volume, logfile, loglevel));
457 0 : goto done;
458 : }
459 :
460 0 : ret = glfs_init(fs);
461 0 : if (ret < 0) {
462 0 : DEBUG(0, ("%s: Failed to initialize volume (%s)\n",
463 : volume, strerror(errno)));
464 0 : goto done;
465 : }
466 :
467 0 : if (!write_behind_pass_through_set) {
468 0 : ret = check_for_write_behind_translator(tmp_ctx, fs, volume);
469 0 : if (ret < 0) {
470 0 : goto done;
471 : }
472 : }
473 :
474 0 : ret = glfs_set_preopened(volume, handle->conn->connectpath, fs);
475 0 : if (ret < 0) {
476 0 : DEBUG(0, ("%s: Failed to register volume (%s)\n",
477 : volume, strerror(errno)));
478 0 : goto done;
479 : }
480 :
481 : /*
482 : * The shadow_copy2 module will fail to export subdirectories
483 : * of a gluster volume unless we specify the mount point,
484 : * because the detection fails if the file system is not
485 : * locally mounted:
486 : * https://bugzilla.samba.org/show_bug.cgi?id=13091
487 : */
488 0 : lp_do_parameter(SNUM(handle->conn), "shadow:mountpoint", "/");
489 :
490 : /*
491 : * Unless we have an async implementation of getxattrat turn this off.
492 : */
493 0 : lp_do_parameter(SNUM(handle->conn), "smbd async dosmode", "false");
494 :
495 0 : done:
496 0 : if (ret < 0) {
497 0 : if (fs)
498 0 : glfs_fini(fs);
499 : } else {
500 0 : DBG_ERR("%s: Initialized volume from servers %s\n",
501 : volume, volfile_servers);
502 0 : handle->data = fs;
503 : }
504 0 : talloc_free(tmp_ctx);
505 0 : return ret;
506 : }
507 :
508 0 : static void vfs_gluster_disconnect(struct vfs_handle_struct *handle)
509 : {
510 0 : glfs_t *fs = NULL;
511 :
512 0 : fs = handle->data;
513 :
514 0 : glfs_clear_preopened(fs);
515 0 : }
516 :
517 0 : static uint64_t vfs_gluster_disk_free(struct vfs_handle_struct *handle,
518 : const struct smb_filename *smb_fname,
519 : uint64_t *bsize_p,
520 : uint64_t *dfree_p,
521 : uint64_t *dsize_p)
522 : {
523 0 : struct statvfs statvfs = { 0, };
524 : int ret;
525 :
526 0 : ret = glfs_statvfs(handle->data, smb_fname->base_name, &statvfs);
527 0 : if (ret < 0) {
528 0 : return -1;
529 : }
530 :
531 0 : if (bsize_p != NULL) {
532 0 : *bsize_p = (uint64_t)statvfs.f_bsize; /* Block size */
533 : }
534 0 : if (dfree_p != NULL) {
535 0 : *dfree_p = (uint64_t)statvfs.f_bavail; /* Available Block units */
536 : }
537 0 : if (dsize_p != NULL) {
538 0 : *dsize_p = (uint64_t)statvfs.f_blocks; /* Total Block units */
539 : }
540 :
541 0 : return (uint64_t)statvfs.f_bavail;
542 : }
543 :
544 0 : static int vfs_gluster_get_quota(struct vfs_handle_struct *handle,
545 : const struct smb_filename *smb_fname,
546 : enum SMB_QUOTA_TYPE qtype,
547 : unid_t id,
548 : SMB_DISK_QUOTA *qt)
549 : {
550 0 : errno = ENOSYS;
551 0 : return -1;
552 : }
553 :
554 : static int
555 0 : vfs_gluster_set_quota(struct vfs_handle_struct *handle,
556 : enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
557 : {
558 0 : errno = ENOSYS;
559 0 : return -1;
560 : }
561 :
562 0 : static int vfs_gluster_statvfs(struct vfs_handle_struct *handle,
563 : const struct smb_filename *smb_fname,
564 : struct vfs_statvfs_struct *vfs_statvfs)
565 : {
566 0 : struct statvfs statvfs = { 0, };
567 : int ret;
568 :
569 0 : ret = glfs_statvfs(handle->data, smb_fname->base_name, &statvfs);
570 0 : if (ret < 0) {
571 0 : DEBUG(0, ("glfs_statvfs(%s) failed: %s\n",
572 : smb_fname->base_name, strerror(errno)));
573 0 : return -1;
574 : }
575 :
576 0 : ZERO_STRUCTP(vfs_statvfs);
577 :
578 0 : vfs_statvfs->OptimalTransferSize = statvfs.f_frsize;
579 0 : vfs_statvfs->BlockSize = statvfs.f_bsize;
580 0 : vfs_statvfs->TotalBlocks = statvfs.f_blocks;
581 0 : vfs_statvfs->BlocksAvail = statvfs.f_bfree;
582 0 : vfs_statvfs->UserBlocksAvail = statvfs.f_bavail;
583 0 : vfs_statvfs->TotalFileNodes = statvfs.f_files;
584 0 : vfs_statvfs->FreeFileNodes = statvfs.f_ffree;
585 0 : vfs_statvfs->FsIdentifier = statvfs.f_fsid;
586 0 : vfs_statvfs->FsCapabilities =
587 : FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
588 :
589 0 : return ret;
590 : }
591 :
592 0 : static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle,
593 : enum timestamp_set_resolution *p_ts_res)
594 : {
595 0 : uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
596 :
597 : #ifdef HAVE_GFAPI_VER_6
598 0 : caps |= FILE_SUPPORTS_SPARSE_FILES;
599 : #endif
600 :
601 : #ifdef STAT_HAVE_NSEC
602 : *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
603 : #endif
604 :
605 0 : return caps;
606 : }
607 :
608 0 : static glfs_fd_t *vfs_gluster_fetch_glfd(struct vfs_handle_struct *handle,
609 : const files_struct *fsp)
610 : {
611 0 : glfs_fd_t **glfd = (glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp);
612 0 : if (glfd == NULL) {
613 0 : DBG_INFO("Failed to fetch fsp extension\n");
614 0 : return NULL;
615 : }
616 0 : if (*glfd == NULL) {
617 0 : DBG_INFO("Empty glfs_fd_t pointer\n");
618 0 : return NULL;
619 : }
620 :
621 0 : return *glfd;
622 : }
623 :
624 0 : static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle,
625 : files_struct *fsp, const char *mask,
626 : uint32_t attributes)
627 : {
628 0 : glfs_fd_t *glfd = NULL;
629 :
630 0 : glfd = glfs_opendir(handle->data, fsp->fsp_name->base_name);
631 0 : if (glfd == NULL) {
632 0 : return NULL;
633 : }
634 :
635 0 : return (DIR *)glfd;
636 : }
637 :
638 0 : static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp)
639 : {
640 : int ret;
641 :
642 0 : START_PROFILE(syscall_closedir);
643 0 : ret = glfs_closedir((void *)dirp);
644 0 : END_PROFILE(syscall_closedir);
645 :
646 0 : return ret;
647 : }
648 :
649 0 : static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle,
650 : struct files_struct *dirfsp,
651 : DIR *dirp,
652 : SMB_STRUCT_STAT *sbuf)
653 : {
654 : static char direntbuf[512];
655 : int ret;
656 : struct stat stat;
657 0 : struct dirent *dirent = 0;
658 :
659 0 : START_PROFILE(syscall_readdir);
660 0 : if (sbuf != NULL) {
661 0 : ret = glfs_readdirplus_r((void *)dirp, &stat, (void *)direntbuf,
662 : &dirent);
663 : } else {
664 0 : ret = glfs_readdir_r((void *)dirp, (void *)direntbuf, &dirent);
665 : }
666 :
667 0 : if ((ret < 0) || (dirent == NULL)) {
668 0 : END_PROFILE(syscall_readdir);
669 0 : return NULL;
670 : }
671 :
672 0 : if (sbuf != NULL) {
673 0 : SET_STAT_INVALID(*sbuf);
674 0 : if (!S_ISLNK(stat.st_mode)) {
675 0 : smb_stat_ex_from_stat(sbuf, &stat);
676 : }
677 : }
678 :
679 0 : END_PROFILE(syscall_readdir);
680 0 : return dirent;
681 : }
682 :
683 0 : static long vfs_gluster_telldir(struct vfs_handle_struct *handle, DIR *dirp)
684 : {
685 : long ret;
686 :
687 0 : START_PROFILE(syscall_telldir);
688 0 : ret = glfs_telldir((void *)dirp);
689 0 : END_PROFILE(syscall_telldir);
690 :
691 0 : return ret;
692 : }
693 :
694 0 : static void vfs_gluster_seekdir(struct vfs_handle_struct *handle, DIR *dirp,
695 : long offset)
696 : {
697 0 : START_PROFILE(syscall_seekdir);
698 0 : glfs_seekdir((void *)dirp, offset);
699 0 : END_PROFILE(syscall_seekdir);
700 0 : }
701 :
702 0 : static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
703 : {
704 0 : START_PROFILE(syscall_rewinddir);
705 0 : glfs_seekdir((void *)dirp, 0);
706 0 : END_PROFILE(syscall_rewinddir);
707 0 : }
708 :
709 0 : static int vfs_gluster_mkdirat(struct vfs_handle_struct *handle,
710 : struct files_struct *dirfsp,
711 : const struct smb_filename *smb_fname,
712 : mode_t mode)
713 : {
714 : int ret;
715 :
716 : #ifdef HAVE_GFAPI_VER_7_11
717 : glfs_fd_t *pglfd = NULL;
718 :
719 : START_PROFILE(syscall_mkdirat);
720 :
721 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
722 : if (pglfd == NULL) {
723 : END_PROFILE(syscall_mkdirat);
724 : DBG_ERR("Failed to fetch gluster fd\n");
725 : return -1;
726 : }
727 :
728 : ret = glfs_mkdirat(pglfd, smb_fname->base_name, mode);
729 : #else
730 0 : struct smb_filename *full_fname = NULL;
731 :
732 0 : START_PROFILE(syscall_mkdirat);
733 :
734 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
735 : dirfsp,
736 : smb_fname);
737 0 : if (full_fname == NULL) {
738 0 : END_PROFILE(syscall_mkdirat);
739 0 : return -1;
740 : }
741 :
742 0 : ret = glfs_mkdir(handle->data, full_fname->base_name, mode);
743 :
744 0 : TALLOC_FREE(full_fname);
745 : #endif
746 :
747 0 : END_PROFILE(syscall_mkdirat);
748 :
749 0 : return ret;
750 : }
751 :
752 0 : static int vfs_gluster_openat(struct vfs_handle_struct *handle,
753 : const struct files_struct *dirfsp,
754 : const struct smb_filename *smb_fname,
755 : files_struct *fsp,
756 : const struct vfs_open_how *how)
757 : {
758 0 : int flags = how->flags;
759 0 : struct smb_filename *full_fname = NULL;
760 0 : bool have_opath = false;
761 0 : bool became_root = false;
762 : glfs_fd_t *glfd;
763 0 : glfs_fd_t *pglfd = NULL;
764 : glfs_fd_t **p_tmp;
765 :
766 0 : START_PROFILE(syscall_openat);
767 :
768 0 : if (how->resolve != 0) {
769 0 : END_PROFILE(syscall_openat);
770 0 : errno = ENOSYS;
771 0 : return -1;
772 : }
773 :
774 0 : p_tmp = VFS_ADD_FSP_EXTENSION(handle, fsp, glfs_fd_t *, NULL);
775 0 : if (p_tmp == NULL) {
776 0 : END_PROFILE(syscall_openat);
777 0 : errno = ENOMEM;
778 0 : return -1;
779 : }
780 :
781 : #ifdef O_PATH
782 0 : have_opath = true;
783 0 : if (fsp->fsp_flags.is_pathref) {
784 0 : flags |= O_PATH;
785 : }
786 : #endif
787 :
788 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
789 : dirfsp,
790 : smb_fname);
791 0 : if (full_fname == NULL) {
792 0 : END_PROFILE(syscall_openat);
793 0 : return -1;
794 : }
795 :
796 0 : if (fsp->fsp_flags.is_pathref && !have_opath) {
797 0 : become_root();
798 0 : became_root = true;
799 : }
800 :
801 0 : if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
802 : #ifdef HAVE_GFAPI_VER_7_11
803 : /*
804 : * Fetch Gluster fd for parent directory using dirfsp
805 : * before calling glfs_openat();
806 : */
807 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
808 : if (pglfd == NULL) {
809 : END_PROFILE(syscall_openat);
810 : DBG_ERR("Failed to fetch gluster fd\n");
811 : return -1;
812 : }
813 :
814 : glfd = glfs_openat(pglfd,
815 : smb_fname->base_name,
816 : flags,
817 : how->mode);
818 : #else
819 : /*
820 : * Replace smb_fname with full_path constructed above.
821 : */
822 0 : smb_fname = full_fname;
823 : #endif
824 : }
825 :
826 0 : if (pglfd == NULL) {
827 : /*
828 : * smb_fname can either be a full_path or the same one
829 : * as received from the caller. In the latter case we
830 : * are operating at current working directory.
831 : */
832 0 : if (flags & O_CREAT) {
833 0 : glfd = glfs_creat(handle->data,
834 0 : smb_fname->base_name,
835 : flags,
836 : how->mode);
837 : } else {
838 0 : glfd = glfs_open(handle->data,
839 0 : smb_fname->base_name,
840 : flags);
841 : }
842 : }
843 :
844 0 : if (became_root) {
845 0 : unbecome_root();
846 : }
847 :
848 0 : TALLOC_FREE(full_fname);
849 :
850 0 : fsp->fsp_flags.have_proc_fds = false;
851 :
852 0 : if (glfd == NULL) {
853 0 : END_PROFILE(syscall_openat);
854 : /* no extension destroy_fn, so no need to save errno */
855 0 : VFS_REMOVE_FSP_EXTENSION(handle, fsp);
856 0 : return -1;
857 : }
858 :
859 0 : *p_tmp = glfd;
860 :
861 0 : END_PROFILE(syscall_openat);
862 : /* An arbitrary value for error reporting, so you know its us. */
863 0 : return 13371337;
864 : }
865 :
866 0 : static int vfs_gluster_close(struct vfs_handle_struct *handle,
867 : files_struct *fsp)
868 : {
869 : int ret;
870 0 : glfs_fd_t *glfd = NULL;
871 :
872 0 : START_PROFILE(syscall_close);
873 :
874 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
875 0 : if (glfd == NULL) {
876 0 : END_PROFILE(syscall_close);
877 0 : DBG_ERR("Failed to fetch gluster fd\n");
878 0 : return -1;
879 : }
880 :
881 0 : VFS_REMOVE_FSP_EXTENSION(handle, fsp);
882 :
883 0 : ret = glfs_close(glfd);
884 0 : END_PROFILE(syscall_close);
885 :
886 0 : return ret;
887 : }
888 :
889 0 : static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle,
890 : files_struct *fsp, void *data, size_t n,
891 : off_t offset)
892 : {
893 : ssize_t ret;
894 0 : glfs_fd_t *glfd = NULL;
895 :
896 0 : START_PROFILE_BYTES(syscall_pread, n);
897 :
898 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
899 0 : if (glfd == NULL) {
900 0 : END_PROFILE_BYTES(syscall_pread);
901 0 : DBG_ERR("Failed to fetch gluster fd\n");
902 0 : return -1;
903 : }
904 :
905 : #ifdef HAVE_GFAPI_VER_7_6
906 : ret = glfs_pread(glfd, data, n, offset, 0, NULL);
907 : #else
908 0 : ret = glfs_pread(glfd, data, n, offset, 0);
909 : #endif
910 0 : END_PROFILE_BYTES(syscall_pread);
911 :
912 0 : return ret;
913 : }
914 :
915 : struct vfs_gluster_pread_state {
916 : ssize_t ret;
917 : glfs_fd_t *fd;
918 : void *buf;
919 : size_t count;
920 : off_t offset;
921 :
922 : struct vfs_aio_state vfs_aio_state;
923 : SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
924 : };
925 :
926 : static void vfs_gluster_pread_do(void *private_data);
927 : static void vfs_gluster_pread_done(struct tevent_req *subreq);
928 : static int vfs_gluster_pread_state_destructor(struct vfs_gluster_pread_state *state);
929 :
930 0 : static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct
931 : *handle, TALLOC_CTX *mem_ctx,
932 : struct tevent_context *ev,
933 : files_struct *fsp,
934 : void *data, size_t n,
935 : off_t offset)
936 : {
937 : struct vfs_gluster_pread_state *state;
938 : struct tevent_req *req, *subreq;
939 :
940 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
941 0 : if (glfd == NULL) {
942 0 : DBG_ERR("Failed to fetch gluster fd\n");
943 0 : return NULL;
944 : }
945 :
946 0 : req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_pread_state);
947 0 : if (req == NULL) {
948 0 : return NULL;
949 : }
950 :
951 0 : state->ret = -1;
952 0 : state->fd = glfd;
953 0 : state->buf = data;
954 0 : state->count = n;
955 0 : state->offset = offset;
956 :
957 0 : SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
958 : state->profile_bytes, n);
959 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
960 :
961 0 : subreq = pthreadpool_tevent_job_send(
962 0 : state, ev, handle->conn->sconn->pool,
963 : vfs_gluster_pread_do, state);
964 0 : if (tevent_req_nomem(subreq, req)) {
965 0 : return tevent_req_post(req, ev);
966 : }
967 0 : tevent_req_set_callback(subreq, vfs_gluster_pread_done, req);
968 :
969 0 : talloc_set_destructor(state, vfs_gluster_pread_state_destructor);
970 :
971 0 : return req;
972 : }
973 :
974 0 : static void vfs_gluster_pread_do(void *private_data)
975 : {
976 0 : struct vfs_gluster_pread_state *state = talloc_get_type_abort(
977 : private_data, struct vfs_gluster_pread_state);
978 : struct timespec start_time;
979 : struct timespec end_time;
980 :
981 0 : SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
982 :
983 0 : PROFILE_TIMESTAMP(&start_time);
984 :
985 : do {
986 : #ifdef HAVE_GFAPI_VER_7_6
987 : state->ret = glfs_pread(state->fd, state->buf, state->count,
988 : state->offset, 0, NULL);
989 : #else
990 0 : state->ret = glfs_pread(state->fd, state->buf, state->count,
991 : state->offset, 0);
992 : #endif
993 0 : } while ((state->ret == -1) && (errno == EINTR));
994 :
995 0 : if (state->ret == -1) {
996 0 : state->vfs_aio_state.error = errno;
997 : }
998 :
999 0 : PROFILE_TIMESTAMP(&end_time);
1000 :
1001 0 : state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1002 :
1003 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1004 0 : }
1005 :
1006 0 : static int vfs_gluster_pread_state_destructor(struct vfs_gluster_pread_state *state)
1007 : {
1008 0 : return -1;
1009 : }
1010 :
1011 0 : static void vfs_gluster_pread_done(struct tevent_req *subreq)
1012 : {
1013 0 : struct tevent_req *req = tevent_req_callback_data(
1014 : subreq, struct tevent_req);
1015 0 : struct vfs_gluster_pread_state *state = tevent_req_data(
1016 : req, struct vfs_gluster_pread_state);
1017 : int ret;
1018 :
1019 0 : ret = pthreadpool_tevent_job_recv(subreq);
1020 0 : TALLOC_FREE(subreq);
1021 0 : SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1022 0 : talloc_set_destructor(state, NULL);
1023 0 : if (ret != 0) {
1024 0 : if (ret != EAGAIN) {
1025 0 : tevent_req_error(req, ret);
1026 0 : return;
1027 : }
1028 : /*
1029 : * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1030 : * means the lower level pthreadpool failed to create a new
1031 : * thread. Fallback to sync processing in that case to allow
1032 : * some progress for the client.
1033 : */
1034 0 : vfs_gluster_pread_do(state);
1035 : }
1036 :
1037 0 : tevent_req_done(req);
1038 : }
1039 :
1040 0 : static ssize_t vfs_gluster_pread_recv(struct tevent_req *req,
1041 : struct vfs_aio_state *vfs_aio_state)
1042 : {
1043 0 : struct vfs_gluster_pread_state *state = tevent_req_data(
1044 : req, struct vfs_gluster_pread_state);
1045 :
1046 0 : if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1047 0 : return -1;
1048 : }
1049 :
1050 0 : *vfs_aio_state = state->vfs_aio_state;
1051 0 : return state->ret;
1052 : }
1053 :
1054 : struct vfs_gluster_pwrite_state {
1055 : ssize_t ret;
1056 : glfs_fd_t *fd;
1057 : const void *buf;
1058 : size_t count;
1059 : off_t offset;
1060 :
1061 : struct vfs_aio_state vfs_aio_state;
1062 : SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1063 : };
1064 :
1065 : static void vfs_gluster_pwrite_do(void *private_data);
1066 : static void vfs_gluster_pwrite_done(struct tevent_req *subreq);
1067 : static int vfs_gluster_pwrite_state_destructor(struct vfs_gluster_pwrite_state *state);
1068 :
1069 0 : static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct
1070 : *handle, TALLOC_CTX *mem_ctx,
1071 : struct tevent_context *ev,
1072 : files_struct *fsp,
1073 : const void *data, size_t n,
1074 : off_t offset)
1075 : {
1076 : struct tevent_req *req, *subreq;
1077 : struct vfs_gluster_pwrite_state *state;
1078 :
1079 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
1080 0 : if (glfd == NULL) {
1081 0 : DBG_ERR("Failed to fetch gluster fd\n");
1082 0 : return NULL;
1083 : }
1084 :
1085 0 : req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_pwrite_state);
1086 0 : if (req == NULL) {
1087 0 : return NULL;
1088 : }
1089 :
1090 0 : state->ret = -1;
1091 0 : state->fd = glfd;
1092 0 : state->buf = data;
1093 0 : state->count = n;
1094 0 : state->offset = offset;
1095 :
1096 0 : SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
1097 : state->profile_bytes, n);
1098 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1099 :
1100 0 : subreq = pthreadpool_tevent_job_send(
1101 0 : state, ev, handle->conn->sconn->pool,
1102 : vfs_gluster_pwrite_do, state);
1103 0 : if (tevent_req_nomem(subreq, req)) {
1104 0 : return tevent_req_post(req, ev);
1105 : }
1106 0 : tevent_req_set_callback(subreq, vfs_gluster_pwrite_done, req);
1107 :
1108 0 : talloc_set_destructor(state, vfs_gluster_pwrite_state_destructor);
1109 :
1110 0 : return req;
1111 : }
1112 :
1113 0 : static void vfs_gluster_pwrite_do(void *private_data)
1114 : {
1115 0 : struct vfs_gluster_pwrite_state *state = talloc_get_type_abort(
1116 : private_data, struct vfs_gluster_pwrite_state);
1117 : struct timespec start_time;
1118 : struct timespec end_time;
1119 :
1120 0 : SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1121 :
1122 0 : PROFILE_TIMESTAMP(&start_time);
1123 :
1124 : do {
1125 : #ifdef HAVE_GFAPI_VER_7_6
1126 : state->ret = glfs_pwrite(state->fd, state->buf, state->count,
1127 : state->offset, 0, NULL, NULL);
1128 : #else
1129 0 : state->ret = glfs_pwrite(state->fd, state->buf, state->count,
1130 : state->offset, 0);
1131 : #endif
1132 0 : } while ((state->ret == -1) && (errno == EINTR));
1133 :
1134 0 : if (state->ret == -1) {
1135 0 : state->vfs_aio_state.error = errno;
1136 : }
1137 :
1138 0 : PROFILE_TIMESTAMP(&end_time);
1139 :
1140 0 : state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1141 :
1142 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1143 0 : }
1144 :
1145 0 : static int vfs_gluster_pwrite_state_destructor(struct vfs_gluster_pwrite_state *state)
1146 : {
1147 0 : return -1;
1148 : }
1149 :
1150 0 : static void vfs_gluster_pwrite_done(struct tevent_req *subreq)
1151 : {
1152 0 : struct tevent_req *req = tevent_req_callback_data(
1153 : subreq, struct tevent_req);
1154 0 : struct vfs_gluster_pwrite_state *state = tevent_req_data(
1155 : req, struct vfs_gluster_pwrite_state);
1156 : int ret;
1157 :
1158 0 : ret = pthreadpool_tevent_job_recv(subreq);
1159 0 : TALLOC_FREE(subreq);
1160 0 : SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1161 0 : talloc_set_destructor(state, NULL);
1162 0 : if (ret != 0) {
1163 0 : if (ret != EAGAIN) {
1164 0 : tevent_req_error(req, ret);
1165 0 : return;
1166 : }
1167 : /*
1168 : * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1169 : * means the lower level pthreadpool failed to create a new
1170 : * thread. Fallback to sync processing in that case to allow
1171 : * some progress for the client.
1172 : */
1173 0 : vfs_gluster_pwrite_do(state);
1174 : }
1175 :
1176 0 : tevent_req_done(req);
1177 : }
1178 :
1179 0 : static ssize_t vfs_gluster_pwrite_recv(struct tevent_req *req,
1180 : struct vfs_aio_state *vfs_aio_state)
1181 : {
1182 0 : struct vfs_gluster_pwrite_state *state = tevent_req_data(
1183 : req, struct vfs_gluster_pwrite_state);
1184 :
1185 0 : if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1186 0 : return -1;
1187 : }
1188 :
1189 0 : *vfs_aio_state = state->vfs_aio_state;
1190 :
1191 0 : return state->ret;
1192 : }
1193 :
1194 0 : static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle,
1195 : files_struct *fsp, const void *data,
1196 : size_t n, off_t offset)
1197 : {
1198 : ssize_t ret;
1199 0 : glfs_fd_t *glfd = NULL;
1200 :
1201 0 : START_PROFILE_BYTES(syscall_pwrite, n);
1202 :
1203 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1204 0 : if (glfd == NULL) {
1205 0 : END_PROFILE_BYTES(syscall_pwrite);
1206 0 : DBG_ERR("Failed to fetch gluster fd\n");
1207 0 : return -1;
1208 : }
1209 :
1210 : #ifdef HAVE_GFAPI_VER_7_6
1211 : ret = glfs_pwrite(glfd, data, n, offset, 0, NULL, NULL);
1212 : #else
1213 0 : ret = glfs_pwrite(glfd, data, n, offset, 0);
1214 : #endif
1215 0 : END_PROFILE_BYTES(syscall_pwrite);
1216 :
1217 0 : return ret;
1218 : }
1219 :
1220 0 : static off_t vfs_gluster_lseek(struct vfs_handle_struct *handle,
1221 : files_struct *fsp, off_t offset, int whence)
1222 : {
1223 0 : off_t ret = 0;
1224 0 : glfs_fd_t *glfd = NULL;
1225 :
1226 0 : START_PROFILE(syscall_lseek);
1227 :
1228 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1229 0 : if (glfd == NULL) {
1230 0 : END_PROFILE(syscall_lseek);
1231 0 : DBG_ERR("Failed to fetch gluster fd\n");
1232 0 : return -1;
1233 : }
1234 :
1235 0 : ret = glfs_lseek(glfd, offset, whence);
1236 0 : END_PROFILE(syscall_lseek);
1237 :
1238 0 : return ret;
1239 : }
1240 :
1241 0 : static ssize_t vfs_gluster_sendfile(struct vfs_handle_struct *handle, int tofd,
1242 : files_struct *fromfsp,
1243 : const DATA_BLOB *hdr,
1244 : off_t offset, size_t n)
1245 : {
1246 0 : errno = ENOTSUP;
1247 0 : return -1;
1248 : }
1249 :
1250 0 : static ssize_t vfs_gluster_recvfile(struct vfs_handle_struct *handle,
1251 : int fromfd, files_struct *tofsp,
1252 : off_t offset, size_t n)
1253 : {
1254 0 : errno = ENOTSUP;
1255 0 : return -1;
1256 : }
1257 :
1258 0 : static int vfs_gluster_renameat(struct vfs_handle_struct *handle,
1259 : files_struct *srcfsp,
1260 : const struct smb_filename *smb_fname_src,
1261 : files_struct *dstfsp,
1262 : const struct smb_filename *smb_fname_dst)
1263 : {
1264 : int ret;
1265 :
1266 : #ifdef HAVE_GFAPI_VER_7_11
1267 : glfs_fd_t *src_pglfd = NULL;
1268 : glfs_fd_t *dst_pglfd = NULL;
1269 :
1270 : START_PROFILE(syscall_renameat);
1271 :
1272 : src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp);
1273 : if (src_pglfd == NULL) {
1274 : END_PROFILE(syscall_renameat);
1275 : DBG_ERR("Failed to fetch gluster fd\n");
1276 : return -1;
1277 : }
1278 :
1279 : dst_pglfd = vfs_gluster_fetch_glfd(handle, dstfsp);
1280 : if (dst_pglfd == NULL) {
1281 : END_PROFILE(syscall_renameat);
1282 : DBG_ERR("Failed to fetch gluster fd\n");
1283 : return -1;
1284 : }
1285 :
1286 : ret = glfs_renameat(src_pglfd, smb_fname_src->base_name,
1287 : dst_pglfd, smb_fname_dst->base_name);
1288 : #else
1289 0 : struct smb_filename *full_fname_src = NULL;
1290 0 : struct smb_filename *full_fname_dst = NULL;
1291 :
1292 0 : START_PROFILE(syscall_renameat);
1293 :
1294 0 : full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
1295 : srcfsp,
1296 : smb_fname_src);
1297 0 : if (full_fname_src == NULL) {
1298 0 : END_PROFILE(syscall_renameat);
1299 0 : errno = ENOMEM;
1300 0 : return -1;
1301 : }
1302 :
1303 0 : full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
1304 : dstfsp,
1305 : smb_fname_dst);
1306 0 : if (full_fname_dst == NULL) {
1307 0 : END_PROFILE(syscall_renameat);
1308 0 : TALLOC_FREE(full_fname_src);
1309 0 : errno = ENOMEM;
1310 0 : return -1;
1311 : }
1312 0 : ret = glfs_rename(handle->data,
1313 0 : full_fname_src->base_name,
1314 0 : full_fname_dst->base_name);
1315 :
1316 0 : TALLOC_FREE(full_fname_src);
1317 0 : TALLOC_FREE(full_fname_dst);
1318 : #endif
1319 :
1320 0 : END_PROFILE(syscall_renameat);
1321 :
1322 0 : return ret;
1323 : }
1324 :
1325 : struct vfs_gluster_fsync_state {
1326 : ssize_t ret;
1327 : glfs_fd_t *fd;
1328 :
1329 : struct vfs_aio_state vfs_aio_state;
1330 : SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1331 : };
1332 :
1333 : static void vfs_gluster_fsync_do(void *private_data);
1334 : static void vfs_gluster_fsync_done(struct tevent_req *subreq);
1335 : static int vfs_gluster_fsync_state_destructor(struct vfs_gluster_fsync_state *state);
1336 :
1337 0 : static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct
1338 : *handle, TALLOC_CTX *mem_ctx,
1339 : struct tevent_context *ev,
1340 : files_struct *fsp)
1341 : {
1342 : struct tevent_req *req, *subreq;
1343 : struct vfs_gluster_fsync_state *state;
1344 :
1345 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
1346 0 : if (glfd == NULL) {
1347 0 : DBG_ERR("Failed to fetch gluster fd\n");
1348 0 : return NULL;
1349 : }
1350 :
1351 0 : req = tevent_req_create(mem_ctx, &state, struct vfs_gluster_fsync_state);
1352 0 : if (req == NULL) {
1353 0 : return NULL;
1354 : }
1355 :
1356 0 : state->ret = -1;
1357 0 : state->fd = glfd;
1358 :
1359 0 : SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1360 : state->profile_bytes, 0);
1361 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1362 :
1363 0 : subreq = pthreadpool_tevent_job_send(
1364 0 : state, ev, handle->conn->sconn->pool, vfs_gluster_fsync_do, state);
1365 0 : if (tevent_req_nomem(subreq, req)) {
1366 0 : return tevent_req_post(req, ev);
1367 : }
1368 0 : tevent_req_set_callback(subreq, vfs_gluster_fsync_done, req);
1369 :
1370 0 : talloc_set_destructor(state, vfs_gluster_fsync_state_destructor);
1371 :
1372 0 : return req;
1373 : }
1374 :
1375 0 : static void vfs_gluster_fsync_do(void *private_data)
1376 : {
1377 0 : struct vfs_gluster_fsync_state *state = talloc_get_type_abort(
1378 : private_data, struct vfs_gluster_fsync_state);
1379 : struct timespec start_time;
1380 : struct timespec end_time;
1381 :
1382 0 : SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1383 :
1384 0 : PROFILE_TIMESTAMP(&start_time);
1385 :
1386 : do {
1387 : #ifdef HAVE_GFAPI_VER_7_6
1388 : state->ret = glfs_fsync(state->fd, NULL, NULL);
1389 : #else
1390 0 : state->ret = glfs_fsync(state->fd);
1391 : #endif
1392 0 : } while ((state->ret == -1) && (errno == EINTR));
1393 :
1394 0 : if (state->ret == -1) {
1395 0 : state->vfs_aio_state.error = errno;
1396 : }
1397 :
1398 0 : PROFILE_TIMESTAMP(&end_time);
1399 :
1400 0 : state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1401 :
1402 0 : SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1403 0 : }
1404 :
1405 0 : static int vfs_gluster_fsync_state_destructor(struct vfs_gluster_fsync_state *state)
1406 : {
1407 0 : return -1;
1408 : }
1409 :
1410 0 : static void vfs_gluster_fsync_done(struct tevent_req *subreq)
1411 : {
1412 0 : struct tevent_req *req = tevent_req_callback_data(
1413 : subreq, struct tevent_req);
1414 0 : struct vfs_gluster_fsync_state *state = tevent_req_data(
1415 : req, struct vfs_gluster_fsync_state);
1416 : int ret;
1417 :
1418 0 : ret = pthreadpool_tevent_job_recv(subreq);
1419 0 : TALLOC_FREE(subreq);
1420 0 : SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1421 0 : talloc_set_destructor(state, NULL);
1422 0 : if (ret != 0) {
1423 0 : if (ret != EAGAIN) {
1424 0 : tevent_req_error(req, ret);
1425 0 : return;
1426 : }
1427 : /*
1428 : * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1429 : * means the lower level pthreadpool failed to create a new
1430 : * thread. Fallback to sync processing in that case to allow
1431 : * some progress for the client.
1432 : */
1433 0 : vfs_gluster_fsync_do(state);
1434 : }
1435 :
1436 0 : tevent_req_done(req);
1437 : }
1438 :
1439 0 : static int vfs_gluster_fsync_recv(struct tevent_req *req,
1440 : struct vfs_aio_state *vfs_aio_state)
1441 : {
1442 0 : struct vfs_gluster_fsync_state *state = tevent_req_data(
1443 : req, struct vfs_gluster_fsync_state);
1444 :
1445 0 : if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1446 0 : return -1;
1447 : }
1448 :
1449 0 : *vfs_aio_state = state->vfs_aio_state;
1450 0 : return state->ret;
1451 : }
1452 :
1453 0 : static int vfs_gluster_stat(struct vfs_handle_struct *handle,
1454 : struct smb_filename *smb_fname)
1455 : {
1456 : struct stat st;
1457 : int ret;
1458 :
1459 0 : START_PROFILE(syscall_stat);
1460 0 : ret = glfs_stat(handle->data, smb_fname->base_name, &st);
1461 0 : if (ret == 0) {
1462 0 : smb_stat_ex_from_stat(&smb_fname->st, &st);
1463 : }
1464 0 : if (ret < 0 && errno != ENOENT) {
1465 0 : DEBUG(0, ("glfs_stat(%s) failed: %s\n",
1466 : smb_fname->base_name, strerror(errno)));
1467 : }
1468 0 : END_PROFILE(syscall_stat);
1469 :
1470 0 : return ret;
1471 : }
1472 :
1473 0 : static int vfs_gluster_fstat(struct vfs_handle_struct *handle,
1474 : files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1475 : {
1476 : struct stat st;
1477 : int ret;
1478 0 : glfs_fd_t *glfd = NULL;
1479 :
1480 0 : START_PROFILE(syscall_fstat);
1481 :
1482 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1483 0 : if (glfd == NULL) {
1484 0 : END_PROFILE(syscall_fstat);
1485 0 : DBG_ERR("Failed to fetch gluster fd\n");
1486 0 : return -1;
1487 : }
1488 :
1489 0 : ret = glfs_fstat(glfd, &st);
1490 0 : if (ret == 0) {
1491 0 : smb_stat_ex_from_stat(sbuf, &st);
1492 : }
1493 0 : if (ret < 0) {
1494 0 : DEBUG(0, ("glfs_fstat(%d) failed: %s\n",
1495 : fsp_get_io_fd(fsp), strerror(errno)));
1496 : }
1497 0 : END_PROFILE(syscall_fstat);
1498 :
1499 0 : return ret;
1500 : }
1501 :
1502 0 : static int vfs_gluster_fstatat(struct vfs_handle_struct *handle,
1503 : const struct files_struct *dirfsp,
1504 : const struct smb_filename *smb_fname,
1505 : SMB_STRUCT_STAT *sbuf,
1506 : int flags)
1507 : {
1508 : struct stat st;
1509 : int ret;
1510 :
1511 : #ifdef HAVE_GFAPI_VER_7_11
1512 : glfs_fd_t *pglfd = NULL;
1513 :
1514 : START_PROFILE(syscall_fstatat);
1515 :
1516 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
1517 : if (pglfd == NULL) {
1518 : END_PROFILE(syscall_fstatat);
1519 : DBG_ERR("Failed to fetch gluster fd\n");
1520 : return -1;
1521 : }
1522 :
1523 : ret = glfs_fstatat(pglfd, smb_fname->base_name, &st, flags);
1524 : #else
1525 0 : struct smb_filename *full_fname = NULL;
1526 :
1527 0 : START_PROFILE(syscall_fstatat);
1528 :
1529 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
1530 : dirfsp,
1531 : smb_fname);
1532 0 : if (full_fname == NULL) {
1533 0 : END_PROFILE(syscall_fstatat);
1534 0 : return -1;
1535 : }
1536 :
1537 0 : ret = glfs_stat(handle->data, full_fname->base_name, &st);
1538 :
1539 0 : TALLOC_FREE(full_fname->base_name);
1540 : #endif
1541 :
1542 0 : if (ret == 0) {
1543 0 : smb_stat_ex_from_stat(sbuf, &st);
1544 : }
1545 :
1546 0 : END_PROFILE(syscall_fstatat);
1547 :
1548 0 : return ret;
1549 : }
1550 :
1551 0 : static int vfs_gluster_lstat(struct vfs_handle_struct *handle,
1552 : struct smb_filename *smb_fname)
1553 : {
1554 : struct stat st;
1555 : int ret;
1556 :
1557 0 : START_PROFILE(syscall_lstat);
1558 0 : ret = glfs_lstat(handle->data, smb_fname->base_name, &st);
1559 0 : if (ret == 0) {
1560 0 : smb_stat_ex_from_stat(&smb_fname->st, &st);
1561 : }
1562 0 : if (ret < 0 && errno != ENOENT) {
1563 0 : DEBUG(0, ("glfs_lstat(%s) failed: %s\n",
1564 : smb_fname->base_name, strerror(errno)));
1565 : }
1566 0 : END_PROFILE(syscall_lstat);
1567 :
1568 0 : return ret;
1569 : }
1570 :
1571 0 : static uint64_t vfs_gluster_get_alloc_size(struct vfs_handle_struct *handle,
1572 : files_struct *fsp,
1573 : const SMB_STRUCT_STAT *sbuf)
1574 : {
1575 : uint64_t ret;
1576 :
1577 0 : START_PROFILE(syscall_get_alloc_size);
1578 0 : ret = sbuf->st_ex_blocks * 512;
1579 0 : END_PROFILE(syscall_get_alloc_size);
1580 :
1581 0 : return ret;
1582 : }
1583 :
1584 0 : static int vfs_gluster_unlinkat(struct vfs_handle_struct *handle,
1585 : struct files_struct *dirfsp,
1586 : const struct smb_filename *smb_fname,
1587 : int flags)
1588 : {
1589 : int ret;
1590 :
1591 : #ifdef HAVE_GFAPI_VER_7_11
1592 : glfs_fd_t *pglfd = NULL;
1593 :
1594 : START_PROFILE(syscall_unlinkat);
1595 :
1596 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
1597 : if (pglfd == NULL) {
1598 : END_PROFILE(syscall_unlinkat);
1599 : DBG_ERR("Failed to fetch gluster fd\n");
1600 : return -1;
1601 : }
1602 :
1603 : ret = glfs_unlinkat(pglfd, smb_fname->base_name, flags);
1604 : #else
1605 0 : struct smb_filename *full_fname = NULL;
1606 :
1607 0 : START_PROFILE(syscall_unlinkat);
1608 :
1609 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
1610 : dirfsp,
1611 : smb_fname);
1612 0 : if (full_fname == NULL) {
1613 0 : END_PROFILE(syscall_unlinkat);
1614 0 : return -1;
1615 : }
1616 :
1617 0 : if (flags & AT_REMOVEDIR) {
1618 0 : ret = glfs_rmdir(handle->data, full_fname->base_name);
1619 : } else {
1620 0 : ret = glfs_unlink(handle->data, full_fname->base_name);
1621 : }
1622 :
1623 0 : TALLOC_FREE(full_fname);
1624 : #endif
1625 :
1626 0 : END_PROFILE(syscall_unlinkat);
1627 :
1628 0 : return ret;
1629 : }
1630 :
1631 0 : static int vfs_gluster_fchmod(struct vfs_handle_struct *handle,
1632 : files_struct *fsp, mode_t mode)
1633 : {
1634 : int ret;
1635 0 : glfs_fd_t *glfd = NULL;
1636 :
1637 0 : START_PROFILE(syscall_fchmod);
1638 :
1639 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1640 0 : if (glfd == NULL) {
1641 0 : END_PROFILE(syscall_fchmod);
1642 0 : DBG_ERR("Failed to fetch gluster fd\n");
1643 0 : return -1;
1644 : }
1645 :
1646 0 : if (!fsp->fsp_flags.is_pathref) {
1647 : /*
1648 : * We can use an io_fd to remove xattrs.
1649 : */
1650 0 : ret = glfs_fchmod(glfd, mode);
1651 : } else {
1652 : /*
1653 : * This is no longer a handle based call.
1654 : */
1655 0 : ret = glfs_chmod(handle->data, fsp->fsp_name->base_name, mode);
1656 : }
1657 0 : END_PROFILE(syscall_fchmod);
1658 :
1659 0 : return ret;
1660 : }
1661 :
1662 0 : static int vfs_gluster_fchown(struct vfs_handle_struct *handle,
1663 : files_struct *fsp, uid_t uid, gid_t gid)
1664 : {
1665 : int ret;
1666 0 : glfs_fd_t *glfd = NULL;
1667 :
1668 0 : START_PROFILE(syscall_fchown);
1669 :
1670 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1671 0 : if (glfd == NULL) {
1672 0 : END_PROFILE(syscall_fchown);
1673 0 : DBG_ERR("Failed to fetch gluster fd\n");
1674 0 : return -1;
1675 : }
1676 :
1677 0 : ret = glfs_fchown(glfd, uid, gid);
1678 0 : END_PROFILE(syscall_fchown);
1679 :
1680 0 : return ret;
1681 : }
1682 :
1683 0 : static int vfs_gluster_lchown(struct vfs_handle_struct *handle,
1684 : const struct smb_filename *smb_fname,
1685 : uid_t uid,
1686 : gid_t gid)
1687 : {
1688 : int ret;
1689 :
1690 0 : START_PROFILE(syscall_lchown);
1691 0 : ret = glfs_lchown(handle->data, smb_fname->base_name, uid, gid);
1692 0 : END_PROFILE(syscall_lchown);
1693 :
1694 0 : return ret;
1695 : }
1696 :
1697 0 : static int vfs_gluster_chdir(struct vfs_handle_struct *handle,
1698 : const struct smb_filename *smb_fname)
1699 : {
1700 : int ret;
1701 :
1702 0 : START_PROFILE(syscall_chdir);
1703 0 : ret = glfs_chdir(handle->data, smb_fname->base_name);
1704 0 : END_PROFILE(syscall_chdir);
1705 :
1706 0 : return ret;
1707 : }
1708 :
1709 0 : static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle,
1710 : TALLOC_CTX *ctx)
1711 : {
1712 0 : char cwd[PATH_MAX] = { '\0' };
1713 : char *ret;
1714 0 : struct smb_filename *smb_fname = NULL;
1715 :
1716 0 : START_PROFILE(syscall_getwd);
1717 :
1718 0 : ret = glfs_getcwd(handle->data, cwd, PATH_MAX - 1);
1719 0 : END_PROFILE(syscall_getwd);
1720 :
1721 0 : if (ret == NULL) {
1722 0 : return NULL;
1723 : }
1724 0 : smb_fname = synthetic_smb_fname(ctx,
1725 : ret,
1726 : NULL,
1727 : NULL,
1728 : 0,
1729 : 0);
1730 0 : return smb_fname;
1731 : }
1732 :
1733 0 : static int vfs_gluster_fntimes(struct vfs_handle_struct *handle,
1734 : files_struct *fsp,
1735 : struct smb_file_time *ft)
1736 : {
1737 0 : int ret = -1;
1738 : struct timespec times[2];
1739 0 : glfs_fd_t *glfd = NULL;
1740 :
1741 0 : START_PROFILE(syscall_fntimes);
1742 :
1743 0 : if (is_omit_timespec(&ft->atime)) {
1744 0 : times[0].tv_sec = fsp->fsp_name->st.st_ex_atime.tv_sec;
1745 0 : times[0].tv_nsec = fsp->fsp_name->st.st_ex_atime.tv_nsec;
1746 : } else {
1747 0 : times[0].tv_sec = ft->atime.tv_sec;
1748 0 : times[0].tv_nsec = ft->atime.tv_nsec;
1749 : }
1750 :
1751 0 : if (is_omit_timespec(&ft->mtime)) {
1752 0 : times[1].tv_sec = fsp->fsp_name->st.st_ex_mtime.tv_sec;
1753 0 : times[1].tv_nsec = fsp->fsp_name->st.st_ex_mtime.tv_nsec;
1754 : } else {
1755 0 : times[1].tv_sec = ft->mtime.tv_sec;
1756 0 : times[1].tv_nsec = ft->mtime.tv_nsec;
1757 : }
1758 :
1759 0 : if ((timespec_compare(×[0],
1760 0 : &fsp->fsp_name->st.st_ex_atime) == 0) &&
1761 0 : (timespec_compare(×[1],
1762 0 : &fsp->fsp_name->st.st_ex_mtime) == 0)) {
1763 0 : END_PROFILE(syscall_fntimes);
1764 0 : return 0;
1765 : }
1766 :
1767 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1768 0 : if (glfd == NULL) {
1769 0 : END_PROFILE(syscall_fntimes);
1770 0 : DBG_ERR("Failed to fetch gluster fd\n");
1771 0 : return -1;
1772 : }
1773 :
1774 0 : if (!fsp->fsp_flags.is_pathref) {
1775 0 : ret = glfs_futimens(glfd, times);
1776 : } else {
1777 0 : ret = glfs_utimens(handle->data,
1778 0 : fsp->fsp_name->base_name,
1779 : times);
1780 : }
1781 0 : END_PROFILE(syscall_fntimes);
1782 :
1783 0 : return ret;
1784 : }
1785 :
1786 0 : static int vfs_gluster_ftruncate(struct vfs_handle_struct *handle,
1787 : files_struct *fsp, off_t offset)
1788 : {
1789 : int ret;
1790 0 : glfs_fd_t *glfd = NULL;
1791 :
1792 0 : START_PROFILE(syscall_ftruncate);
1793 :
1794 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1795 0 : if (glfd == NULL) {
1796 0 : END_PROFILE(syscall_ftruncate);
1797 0 : DBG_ERR("Failed to fetch gluster fd\n");
1798 0 : return -1;
1799 : }
1800 :
1801 : #ifdef HAVE_GFAPI_VER_7_6
1802 : ret = glfs_ftruncate(glfd, offset, NULL, NULL);
1803 : #else
1804 0 : ret = glfs_ftruncate(glfd, offset);
1805 : #endif
1806 0 : END_PROFILE(syscall_ftruncate);
1807 :
1808 0 : return ret;
1809 : }
1810 :
1811 0 : static int vfs_gluster_fallocate(struct vfs_handle_struct *handle,
1812 : struct files_struct *fsp,
1813 : uint32_t mode,
1814 : off_t offset, off_t len)
1815 : {
1816 : int ret;
1817 : #ifdef HAVE_GFAPI_VER_6
1818 0 : glfs_fd_t *glfd = NULL;
1819 : int keep_size, punch_hole;
1820 :
1821 0 : START_PROFILE(syscall_fallocate);
1822 :
1823 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1824 0 : if (glfd == NULL) {
1825 0 : END_PROFILE(syscall_fallocate);
1826 0 : DBG_ERR("Failed to fetch gluster fd\n");
1827 0 : return -1;
1828 : }
1829 :
1830 0 : keep_size = mode & VFS_FALLOCATE_FL_KEEP_SIZE;
1831 0 : punch_hole = mode & VFS_FALLOCATE_FL_PUNCH_HOLE;
1832 :
1833 0 : mode &= ~(VFS_FALLOCATE_FL_KEEP_SIZE|VFS_FALLOCATE_FL_PUNCH_HOLE);
1834 0 : if (mode != 0) {
1835 0 : END_PROFILE(syscall_fallocate);
1836 0 : errno = ENOTSUP;
1837 0 : return -1;
1838 : }
1839 :
1840 0 : if (punch_hole) {
1841 0 : ret = glfs_discard(glfd, offset, len);
1842 0 : if (ret != 0) {
1843 0 : DBG_DEBUG("glfs_discard failed: %s\n",
1844 : strerror(errno));
1845 : }
1846 : }
1847 :
1848 0 : ret = glfs_fallocate(glfd, keep_size, offset, len);
1849 0 : END_PROFILE(syscall_fallocate);
1850 : #else
1851 : errno = ENOTSUP;
1852 : ret = -1;
1853 : #endif
1854 0 : return ret;
1855 : }
1856 :
1857 0 : static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle,
1858 : TALLOC_CTX *ctx,
1859 : const struct smb_filename *smb_fname)
1860 : {
1861 0 : char *result = NULL;
1862 0 : struct smb_filename *result_fname = NULL;
1863 0 : char *resolved_path = NULL;
1864 :
1865 0 : START_PROFILE(syscall_realpath);
1866 :
1867 0 : resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
1868 0 : if (resolved_path == NULL) {
1869 0 : END_PROFILE(syscall_realpath);
1870 0 : errno = ENOMEM;
1871 0 : return NULL;
1872 : }
1873 :
1874 0 : result = glfs_realpath(handle->data,
1875 0 : smb_fname->base_name,
1876 : resolved_path);
1877 0 : if (result != NULL) {
1878 0 : result_fname = synthetic_smb_fname(ctx,
1879 : result,
1880 : NULL,
1881 : NULL,
1882 : 0,
1883 : 0);
1884 : }
1885 :
1886 0 : SAFE_FREE(resolved_path);
1887 0 : END_PROFILE(syscall_realpath);
1888 :
1889 0 : return result_fname;
1890 : }
1891 :
1892 0 : static bool vfs_gluster_lock(struct vfs_handle_struct *handle,
1893 : files_struct *fsp, int op, off_t offset,
1894 : off_t count, int type)
1895 : {
1896 0 : struct flock flock = { 0, };
1897 : int ret;
1898 0 : glfs_fd_t *glfd = NULL;
1899 0 : bool ok = false;
1900 :
1901 0 : START_PROFILE(syscall_fcntl_lock);
1902 :
1903 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1904 0 : if (glfd == NULL) {
1905 0 : DBG_ERR("Failed to fetch gluster fd\n");
1906 0 : ok = false;
1907 0 : goto out;
1908 : }
1909 :
1910 0 : flock.l_type = type;
1911 0 : flock.l_whence = SEEK_SET;
1912 0 : flock.l_start = offset;
1913 0 : flock.l_len = count;
1914 0 : flock.l_pid = 0;
1915 :
1916 0 : ret = glfs_posix_lock(glfd, op, &flock);
1917 :
1918 0 : if (op == F_GETLK) {
1919 : /* lock query, true if someone else has locked */
1920 0 : if ((ret != -1) &&
1921 0 : (flock.l_type != F_UNLCK) &&
1922 0 : (flock.l_pid != 0) && (flock.l_pid != getpid())) {
1923 0 : ok = true;
1924 0 : goto out;
1925 : }
1926 : /* not me */
1927 0 : ok = false;
1928 0 : goto out;
1929 : }
1930 :
1931 0 : if (ret == -1) {
1932 0 : ok = false;
1933 0 : goto out;
1934 : }
1935 :
1936 0 : ok = true;
1937 0 : out:
1938 0 : END_PROFILE(syscall_fcntl_lock);
1939 :
1940 0 : return ok;
1941 : }
1942 :
1943 0 : static int vfs_gluster_filesystem_sharemode(struct vfs_handle_struct *handle,
1944 : files_struct *fsp,
1945 : uint32_t share_access,
1946 : uint32_t access_mask)
1947 : {
1948 0 : errno = ENOSYS;
1949 0 : return -1;
1950 : }
1951 :
1952 0 : static int vfs_gluster_fcntl(vfs_handle_struct *handle,
1953 : files_struct *fsp, int cmd, va_list cmd_arg)
1954 : {
1955 : /*
1956 : * SMB_VFS_FCNTL() is currently only called by vfs_set_blocking() to
1957 : * clear O_NONBLOCK, etc for LOCK_MAND and FIFOs. Ignore it.
1958 : */
1959 0 : if (cmd == F_GETFL) {
1960 0 : return 0;
1961 0 : } else if (cmd == F_SETFL) {
1962 : va_list dup_cmd_arg;
1963 : int opt;
1964 :
1965 0 : va_copy(dup_cmd_arg, cmd_arg);
1966 0 : opt = va_arg(dup_cmd_arg, int);
1967 0 : va_end(dup_cmd_arg);
1968 0 : if (opt == 0) {
1969 0 : return 0;
1970 : }
1971 0 : DBG_ERR("unexpected fcntl SETFL(%d)\n", opt);
1972 0 : goto err_out;
1973 : }
1974 0 : DBG_ERR("unexpected fcntl: %d\n", cmd);
1975 0 : err_out:
1976 0 : errno = EINVAL;
1977 0 : return -1;
1978 : }
1979 :
1980 0 : static int vfs_gluster_linux_setlease(struct vfs_handle_struct *handle,
1981 : files_struct *fsp, int leasetype)
1982 : {
1983 0 : errno = ENOSYS;
1984 0 : return -1;
1985 : }
1986 :
1987 0 : static bool vfs_gluster_getlock(struct vfs_handle_struct *handle,
1988 : files_struct *fsp, off_t *poffset,
1989 : off_t *pcount, int *ptype, pid_t *ppid)
1990 : {
1991 0 : struct flock flock = { 0, };
1992 : int ret;
1993 0 : glfs_fd_t *glfd = NULL;
1994 :
1995 0 : START_PROFILE(syscall_fcntl_getlock);
1996 :
1997 0 : glfd = vfs_gluster_fetch_glfd(handle, fsp);
1998 0 : if (glfd == NULL) {
1999 0 : END_PROFILE(syscall_fcntl_getlock);
2000 0 : DBG_ERR("Failed to fetch gluster fd\n");
2001 0 : return false;
2002 : }
2003 :
2004 0 : flock.l_type = *ptype;
2005 0 : flock.l_whence = SEEK_SET;
2006 0 : flock.l_start = *poffset;
2007 0 : flock.l_len = *pcount;
2008 0 : flock.l_pid = 0;
2009 :
2010 0 : ret = glfs_posix_lock(glfd, F_GETLK, &flock);
2011 :
2012 0 : if (ret == -1) {
2013 0 : END_PROFILE(syscall_fcntl_getlock);
2014 0 : return false;
2015 : }
2016 :
2017 0 : *ptype = flock.l_type;
2018 0 : *poffset = flock.l_start;
2019 0 : *pcount = flock.l_len;
2020 0 : *ppid = flock.l_pid;
2021 0 : END_PROFILE(syscall_fcntl_getlock);
2022 :
2023 0 : return true;
2024 : }
2025 :
2026 0 : static int vfs_gluster_symlinkat(struct vfs_handle_struct *handle,
2027 : const struct smb_filename *link_target,
2028 : struct files_struct *dirfsp,
2029 : const struct smb_filename *new_smb_fname)
2030 : {
2031 : int ret;
2032 :
2033 : #ifdef HAVE_GFAPI_VER_7_11
2034 : glfs_fd_t *pglfd = NULL;
2035 :
2036 : START_PROFILE(syscall_symlinkat);
2037 :
2038 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
2039 : if (pglfd == NULL) {
2040 : END_PROFILE(syscall_symlinkat);
2041 : DBG_ERR("Failed to fetch gluster fd\n");
2042 : return -1;
2043 : }
2044 :
2045 : ret = glfs_symlinkat(link_target->base_name,
2046 : pglfd,
2047 : new_smb_fname->base_name);
2048 : #else
2049 0 : struct smb_filename *full_fname = NULL;
2050 :
2051 0 : START_PROFILE(syscall_symlinkat);
2052 :
2053 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
2054 : dirfsp,
2055 : new_smb_fname);
2056 0 : if (full_fname == NULL) {
2057 0 : END_PROFILE(syscall_symlinkat);
2058 0 : return -1;
2059 : }
2060 :
2061 0 : ret = glfs_symlink(handle->data,
2062 0 : link_target->base_name,
2063 0 : full_fname->base_name);
2064 :
2065 0 : TALLOC_FREE(full_fname);
2066 : #endif
2067 :
2068 0 : END_PROFILE(syscall_symlinkat);
2069 :
2070 0 : return ret;
2071 : }
2072 :
2073 0 : static int vfs_gluster_readlinkat(struct vfs_handle_struct *handle,
2074 : const struct files_struct *dirfsp,
2075 : const struct smb_filename *smb_fname,
2076 : char *buf,
2077 : size_t bufsiz)
2078 : {
2079 : int ret;
2080 :
2081 : #ifdef HAVE_GFAPI_VER_7_11
2082 : glfs_fd_t *pglfd = NULL;
2083 :
2084 : START_PROFILE(syscall_readlinkat);
2085 :
2086 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
2087 : if (pglfd == NULL) {
2088 : END_PROFILE(syscall_readlinkat);
2089 : DBG_ERR("Failed to fetch gluster fd\n");
2090 : return -1;
2091 : }
2092 :
2093 : ret = glfs_readlinkat(pglfd, smb_fname->base_name, buf, bufsiz);
2094 : #else
2095 0 : struct smb_filename *full_fname = NULL;
2096 :
2097 0 : START_PROFILE(syscall_readlinkat);
2098 :
2099 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
2100 : dirfsp,
2101 : smb_fname);
2102 0 : if (full_fname == NULL) {
2103 0 : END_PROFILE(syscall_readlinkat);
2104 0 : return -1;
2105 : }
2106 :
2107 0 : ret = glfs_readlink(handle->data, full_fname->base_name, buf, bufsiz);
2108 :
2109 0 : TALLOC_FREE(full_fname);
2110 : #endif
2111 :
2112 0 : END_PROFILE(syscall_readlinkat);
2113 :
2114 0 : return ret;
2115 : }
2116 :
2117 0 : static int vfs_gluster_linkat(struct vfs_handle_struct *handle,
2118 : files_struct *srcfsp,
2119 : const struct smb_filename *old_smb_fname,
2120 : files_struct *dstfsp,
2121 : const struct smb_filename *new_smb_fname,
2122 : int flags)
2123 : {
2124 : int ret;
2125 :
2126 : #ifdef HAVE_GFAPI_VER_7_11
2127 : glfs_fd_t *src_pglfd = NULL;
2128 : glfs_fd_t *dst_pglfd = NULL;
2129 :
2130 : START_PROFILE(syscall_linkat);
2131 :
2132 : src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp);
2133 : if (src_pglfd == NULL) {
2134 : END_PROFILE(syscall_linkat);
2135 : DBG_ERR("Failed to fetch gluster fd\n");
2136 : return -1;
2137 : }
2138 :
2139 : dst_pglfd = vfs_gluster_fetch_glfd(handle, dstfsp);
2140 : if (dst_pglfd == NULL) {
2141 : END_PROFILE(syscall_linkat);
2142 : DBG_ERR("Failed to fetch gluster fd\n");
2143 : return -1;
2144 : }
2145 :
2146 : ret = glfs_linkat(src_pglfd,
2147 : old_smb_fname->base_name,
2148 : dst_pglfd,
2149 : new_smb_fname->base_name,
2150 : flags);
2151 : #else
2152 0 : struct smb_filename *full_fname_old = NULL;
2153 0 : struct smb_filename *full_fname_new = NULL;
2154 :
2155 0 : START_PROFILE(syscall_linkat);
2156 :
2157 0 : full_fname_old = full_path_from_dirfsp_atname(talloc_tos(),
2158 : srcfsp,
2159 : old_smb_fname);
2160 0 : if (full_fname_old == NULL) {
2161 0 : END_PROFILE(syscall_linkat);
2162 0 : return -1;
2163 : }
2164 :
2165 0 : full_fname_new = full_path_from_dirfsp_atname(talloc_tos(),
2166 : dstfsp,
2167 : new_smb_fname);
2168 0 : if (full_fname_new == NULL) {
2169 0 : END_PROFILE(syscall_linkat);
2170 0 : TALLOC_FREE(full_fname_old);
2171 0 : return -1;
2172 : }
2173 :
2174 0 : ret = glfs_link(handle->data,
2175 0 : full_fname_old->base_name,
2176 0 : full_fname_new->base_name);
2177 :
2178 0 : TALLOC_FREE(full_fname_old);
2179 0 : TALLOC_FREE(full_fname_new);
2180 : #endif
2181 :
2182 0 : END_PROFILE(syscall_linkat);
2183 :
2184 0 : return ret;
2185 : }
2186 :
2187 0 : static int vfs_gluster_mknodat(struct vfs_handle_struct *handle,
2188 : files_struct *dirfsp,
2189 : const struct smb_filename *smb_fname,
2190 : mode_t mode,
2191 : SMB_DEV_T dev)
2192 : {
2193 : int ret;
2194 :
2195 : #ifdef HAVE_GFAPI_VER_7_11
2196 : glfs_fd_t *pglfd = NULL;
2197 :
2198 : START_PROFILE(syscall_mknodat);
2199 :
2200 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
2201 : if (pglfd == NULL) {
2202 : END_PROFILE(syscall_mknodat);
2203 : DBG_ERR("Failed to fetch gluster fd\n");
2204 : return -1;
2205 : }
2206 :
2207 : ret = glfs_mknodat(pglfd, smb_fname->base_name, mode, dev);
2208 : #else
2209 0 : struct smb_filename *full_fname = NULL;
2210 :
2211 0 : START_PROFILE(syscall_mknodat);
2212 :
2213 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
2214 : dirfsp,
2215 : smb_fname);
2216 0 : if (full_fname == NULL) {
2217 0 : END_PROFILE(syscall_mknodat);
2218 0 : return -1;
2219 : }
2220 :
2221 0 : ret = glfs_mknod(handle->data, full_fname->base_name, mode, dev);
2222 :
2223 0 : TALLOC_FREE(full_fname);
2224 : #endif
2225 :
2226 0 : END_PROFILE(syscall_mknodat);
2227 :
2228 0 : return ret;
2229 : }
2230 :
2231 0 : static int vfs_gluster_fchflags(struct vfs_handle_struct *handle,
2232 : struct files_struct *fsp,
2233 : unsigned int flags)
2234 : {
2235 0 : errno = ENOSYS;
2236 0 : return -1;
2237 : }
2238 :
2239 0 : static NTSTATUS vfs_gluster_get_real_filename_at(
2240 : struct vfs_handle_struct *handle,
2241 : struct files_struct *dirfsp,
2242 : const char *name,
2243 : TALLOC_CTX *mem_ctx,
2244 : char **found_name)
2245 : {
2246 : int ret;
2247 : char key_buf[GLUSTER_NAME_MAX + 64];
2248 : char val_buf[GLUSTER_NAME_MAX + 1];
2249 :
2250 0 : if (strlen(name) >= GLUSTER_NAME_MAX) {
2251 0 : return NT_STATUS_OBJECT_NAME_INVALID;
2252 : }
2253 :
2254 0 : snprintf(key_buf, GLUSTER_NAME_MAX + 64,
2255 : "glusterfs.get_real_filename:%s", name);
2256 :
2257 0 : ret = glfs_getxattr(handle->data,
2258 0 : dirfsp->fsp_name->base_name,
2259 : key_buf,
2260 : val_buf,
2261 : GLUSTER_NAME_MAX + 1);
2262 0 : if (ret == -1) {
2263 0 : if (errno == ENOATTR) {
2264 0 : errno = ENOENT;
2265 : }
2266 0 : return map_nt_error_from_unix(errno);
2267 : }
2268 :
2269 0 : *found_name = talloc_strdup(mem_ctx, val_buf);
2270 0 : if (found_name[0] == NULL) {
2271 0 : return NT_STATUS_NO_MEMORY;
2272 : }
2273 :
2274 0 : return NT_STATUS_OK;
2275 : }
2276 :
2277 0 : static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle,
2278 : const struct smb_filename *smb_fname)
2279 : {
2280 0 : return handle->conn->connectpath;
2281 : }
2282 :
2283 : /* EA Operations */
2284 :
2285 0 : static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle,
2286 : files_struct *fsp, const char *name,
2287 : void *value, size_t size)
2288 : {
2289 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
2290 0 : if (glfd == NULL) {
2291 0 : DBG_ERR("Failed to fetch gluster fd\n");
2292 0 : return -1;
2293 : }
2294 :
2295 0 : if (!fsp->fsp_flags.is_pathref) {
2296 : /*
2297 : * We can use an io_fd to retrieve xattr value.
2298 : */
2299 0 : return glfs_fgetxattr(glfd, name, value, size);
2300 : }
2301 :
2302 : /*
2303 : * This is no longer a handle based call.
2304 : */
2305 0 : return glfs_getxattr(handle->data,
2306 0 : fsp->fsp_name->base_name,
2307 : name,
2308 : value,
2309 : size);
2310 : }
2311 :
2312 0 : static ssize_t vfs_gluster_flistxattr(struct vfs_handle_struct *handle,
2313 : files_struct *fsp, char *list,
2314 : size_t size)
2315 : {
2316 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
2317 0 : if (glfd == NULL) {
2318 0 : DBG_ERR("Failed to fetch gluster fd\n");
2319 0 : return -1;
2320 : }
2321 0 : if (!fsp->fsp_flags.is_pathref) {
2322 : /*
2323 : * We can use an io_fd to list xattrs.
2324 : */
2325 0 : return glfs_flistxattr(glfd, list, size);
2326 : } else {
2327 : /*
2328 : * This is no longer a handle based call.
2329 : */
2330 0 : return glfs_listxattr(handle->data,
2331 0 : fsp->fsp_name->base_name,
2332 : list,
2333 : size);
2334 : }
2335 : }
2336 :
2337 0 : static int vfs_gluster_fremovexattr(struct vfs_handle_struct *handle,
2338 : files_struct *fsp, const char *name)
2339 : {
2340 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
2341 0 : if (glfd == NULL) {
2342 0 : DBG_ERR("Failed to fetch gluster fd\n");
2343 0 : return -1;
2344 : }
2345 0 : if (!fsp->fsp_flags.is_pathref) {
2346 : /*
2347 : * We can use an io_fd to remove xattrs.
2348 : */
2349 0 : return glfs_fremovexattr(glfd, name);
2350 : } else {
2351 : /*
2352 : * This is no longer a handle based call.
2353 : */
2354 0 : return glfs_removexattr(handle->data,
2355 0 : fsp->fsp_name->base_name,
2356 : name);
2357 : }
2358 : }
2359 :
2360 0 : static int vfs_gluster_fsetxattr(struct vfs_handle_struct *handle,
2361 : files_struct *fsp, const char *name,
2362 : const void *value, size_t size, int flags)
2363 : {
2364 0 : glfs_fd_t *glfd = vfs_gluster_fetch_glfd(handle, fsp);
2365 0 : if (glfd == NULL) {
2366 0 : DBG_ERR("Failed to fetch gluster fd\n");
2367 0 : return -1;
2368 : }
2369 :
2370 0 : if (!fsp->fsp_flags.is_pathref) {
2371 : /*
2372 : * We can use an io_fd to set xattrs.
2373 : */
2374 0 : return glfs_fsetxattr(glfd, name, value, size, flags);
2375 : } else {
2376 : /*
2377 : * This is no longer a handle based call.
2378 : */
2379 0 : return glfs_setxattr(handle->data,
2380 0 : fsp->fsp_name->base_name,
2381 : name,
2382 : value,
2383 : size,
2384 : flags);
2385 : }
2386 : }
2387 :
2388 : /* AIO Operations */
2389 :
2390 0 : static bool vfs_gluster_aio_force(struct vfs_handle_struct *handle,
2391 : files_struct *fsp)
2392 : {
2393 0 : return false;
2394 : }
2395 :
2396 0 : static NTSTATUS vfs_gluster_create_dfs_pathat(struct vfs_handle_struct *handle,
2397 : struct files_struct *dirfsp,
2398 : const struct smb_filename *smb_fname,
2399 : const struct referral *reflist,
2400 : size_t referral_count)
2401 : {
2402 0 : TALLOC_CTX *frame = talloc_stackframe();
2403 0 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2404 : int ret;
2405 0 : char *msdfs_link = NULL;
2406 : #ifdef HAVE_GFAPI_VER_7_11
2407 : glfs_fd_t *pglfd = NULL;
2408 : #else
2409 0 : struct smb_filename *full_fname = NULL;
2410 : #endif
2411 :
2412 : /* Form the msdfs_link contents */
2413 0 : msdfs_link = msdfs_link_string(frame,
2414 : reflist,
2415 : referral_count);
2416 0 : if (msdfs_link == NULL) {
2417 0 : goto out;
2418 : }
2419 :
2420 : #ifdef HAVE_GFAPI_VER_7_11
2421 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
2422 : if (pglfd == NULL) {
2423 : DBG_ERR("Failed to fetch gluster fd\n");
2424 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2425 : goto out;
2426 : }
2427 :
2428 : ret = glfs_symlinkat(msdfs_link, pglfd, smb_fname->base_name);
2429 : #else
2430 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
2431 : dirfsp,
2432 : smb_fname);
2433 0 : if (full_fname == NULL) {
2434 0 : goto out;
2435 : }
2436 :
2437 0 : ret = glfs_symlink(handle->data, msdfs_link, full_fname->base_name);
2438 :
2439 0 : TALLOC_FREE(full_fname);
2440 : #endif
2441 0 : if (ret == 0) {
2442 0 : status = NT_STATUS_OK;
2443 : } else {
2444 0 : status = map_nt_error_from_unix(errno);
2445 : }
2446 :
2447 0 : out:
2448 :
2449 0 : TALLOC_FREE(frame);
2450 0 : return status;
2451 : }
2452 :
2453 : /*
2454 : * Read and return the contents of a DFS redirect given a
2455 : * pathname. A caller can pass in NULL for ppreflist and
2456 : * preferral_count but still determine if this was a
2457 : * DFS redirect point by getting NT_STATUS_OK back
2458 : * without incurring the overhead of reading and parsing
2459 : * the referral contents.
2460 : */
2461 :
2462 0 : static NTSTATUS vfs_gluster_read_dfs_pathat(struct vfs_handle_struct *handle,
2463 : TALLOC_CTX *mem_ctx,
2464 : struct files_struct *dirfsp,
2465 : struct smb_filename *smb_fname,
2466 : struct referral **ppreflist,
2467 : size_t *preferral_count)
2468 : {
2469 0 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2470 : size_t bufsize;
2471 0 : char *link_target = NULL;
2472 : int referral_len;
2473 : bool ok;
2474 : #if defined(HAVE_BROKEN_READLINK)
2475 : char link_target_buf[PATH_MAX];
2476 : #else
2477 : char link_target_buf[7];
2478 : #endif
2479 : struct stat st;
2480 0 : struct smb_filename *full_fname = NULL;
2481 : int ret;
2482 : #ifdef HAVE_GFAPI_VER_7_11
2483 : glfs_fd_t *pglfd = NULL;
2484 : #endif
2485 :
2486 0 : if (is_named_stream(smb_fname)) {
2487 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2488 0 : goto err;
2489 : }
2490 :
2491 0 : if (ppreflist == NULL && preferral_count == NULL) {
2492 : /*
2493 : * We're only checking if this is a DFS
2494 : * redirect. We don't need to return data.
2495 : */
2496 0 : bufsize = sizeof(link_target_buf);
2497 0 : link_target = link_target_buf;
2498 : } else {
2499 0 : bufsize = PATH_MAX;
2500 0 : link_target = talloc_array(mem_ctx, char, bufsize);
2501 0 : if (!link_target) {
2502 0 : goto err;
2503 : }
2504 : }
2505 :
2506 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
2507 : dirfsp,
2508 : smb_fname);
2509 0 : if (full_fname == NULL) {
2510 0 : status = NT_STATUS_NO_MEMORY;
2511 0 : goto err;
2512 : }
2513 :
2514 0 : ret = glfs_lstat(handle->data, full_fname->base_name, &st);
2515 0 : if (ret < 0) {
2516 0 : status = map_nt_error_from_unix(errno);
2517 0 : goto err;
2518 : }
2519 :
2520 : #ifdef HAVE_GFAPI_VER_7_11
2521 : pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
2522 : if (pglfd == NULL) {
2523 : DBG_ERR("Failed to fetch gluster fd\n");
2524 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2525 : }
2526 :
2527 : referral_len = glfs_readlinkat(pglfd,
2528 : smb_fname->base_name,
2529 : link_target,
2530 : bufsize - 1);
2531 : #else
2532 0 : referral_len = glfs_readlink(handle->data,
2533 0 : full_fname->base_name,
2534 : link_target,
2535 : bufsize - 1);
2536 : #endif
2537 0 : if (referral_len < 0) {
2538 0 : if (errno == EINVAL) {
2539 0 : DBG_INFO("%s is not a link.\n", full_fname->base_name);
2540 0 : status = NT_STATUS_OBJECT_TYPE_MISMATCH;
2541 : } else {
2542 0 : status = map_nt_error_from_unix(errno);
2543 0 : DBG_ERR("Error reading "
2544 : "msdfs link %s: %s\n",
2545 : full_fname->base_name,
2546 : strerror(errno));
2547 : }
2548 0 : goto err;
2549 : }
2550 0 : link_target[referral_len] = '\0';
2551 :
2552 0 : DBG_INFO("%s -> %s\n",
2553 : full_fname->base_name,
2554 : link_target);
2555 :
2556 0 : if (!strnequal(link_target, "msdfs:", 6)) {
2557 0 : status = NT_STATUS_OBJECT_TYPE_MISMATCH;
2558 0 : goto err;
2559 : }
2560 :
2561 0 : if (ppreflist == NULL && preferral_count == NULL) {
2562 : /* Early return for checking if this is a DFS link. */
2563 0 : TALLOC_FREE(full_fname);
2564 0 : smb_stat_ex_from_stat(&smb_fname->st, &st);
2565 0 : return NT_STATUS_OK;
2566 : }
2567 :
2568 0 : ok = parse_msdfs_symlink(mem_ctx,
2569 0 : lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
2570 : link_target,
2571 : ppreflist,
2572 : preferral_count);
2573 :
2574 0 : if (ok) {
2575 0 : smb_stat_ex_from_stat(&smb_fname->st, &st);
2576 0 : status = NT_STATUS_OK;
2577 : } else {
2578 0 : status = NT_STATUS_NO_MEMORY;
2579 : }
2580 :
2581 0 : err:
2582 :
2583 0 : if (link_target != link_target_buf) {
2584 0 : TALLOC_FREE(link_target);
2585 : }
2586 0 : TALLOC_FREE(full_fname);
2587 0 : return status;
2588 : }
2589 :
2590 : static struct vfs_fn_pointers glusterfs_fns = {
2591 :
2592 : /* Disk Operations */
2593 :
2594 : .connect_fn = vfs_gluster_connect,
2595 : .disconnect_fn = vfs_gluster_disconnect,
2596 : .disk_free_fn = vfs_gluster_disk_free,
2597 : .get_quota_fn = vfs_gluster_get_quota,
2598 : .set_quota_fn = vfs_gluster_set_quota,
2599 : .statvfs_fn = vfs_gluster_statvfs,
2600 : .fs_capabilities_fn = vfs_gluster_fs_capabilities,
2601 :
2602 : .get_dfs_referrals_fn = NULL,
2603 :
2604 : /* Directory Operations */
2605 :
2606 : .fdopendir_fn = vfs_gluster_fdopendir,
2607 : .readdir_fn = vfs_gluster_readdir,
2608 : .seekdir_fn = vfs_gluster_seekdir,
2609 : .telldir_fn = vfs_gluster_telldir,
2610 : .rewind_dir_fn = vfs_gluster_rewinddir,
2611 : .mkdirat_fn = vfs_gluster_mkdirat,
2612 : .closedir_fn = vfs_gluster_closedir,
2613 :
2614 : /* File Operations */
2615 :
2616 : .openat_fn = vfs_gluster_openat,
2617 : .create_file_fn = NULL,
2618 : .close_fn = vfs_gluster_close,
2619 : .pread_fn = vfs_gluster_pread,
2620 : .pread_send_fn = vfs_gluster_pread_send,
2621 : .pread_recv_fn = vfs_gluster_pread_recv,
2622 : .pwrite_fn = vfs_gluster_pwrite,
2623 : .pwrite_send_fn = vfs_gluster_pwrite_send,
2624 : .pwrite_recv_fn = vfs_gluster_pwrite_recv,
2625 : .lseek_fn = vfs_gluster_lseek,
2626 : .sendfile_fn = vfs_gluster_sendfile,
2627 : .recvfile_fn = vfs_gluster_recvfile,
2628 : .renameat_fn = vfs_gluster_renameat,
2629 : .fsync_send_fn = vfs_gluster_fsync_send,
2630 : .fsync_recv_fn = vfs_gluster_fsync_recv,
2631 :
2632 : .stat_fn = vfs_gluster_stat,
2633 : .fstat_fn = vfs_gluster_fstat,
2634 : .fstatat_fn = vfs_gluster_fstatat,
2635 : .lstat_fn = vfs_gluster_lstat,
2636 : .get_alloc_size_fn = vfs_gluster_get_alloc_size,
2637 : .unlinkat_fn = vfs_gluster_unlinkat,
2638 :
2639 : .fchmod_fn = vfs_gluster_fchmod,
2640 : .fchown_fn = vfs_gluster_fchown,
2641 : .lchown_fn = vfs_gluster_lchown,
2642 : .chdir_fn = vfs_gluster_chdir,
2643 : .getwd_fn = vfs_gluster_getwd,
2644 : .fntimes_fn = vfs_gluster_fntimes,
2645 : .ftruncate_fn = vfs_gluster_ftruncate,
2646 : .fallocate_fn = vfs_gluster_fallocate,
2647 : .lock_fn = vfs_gluster_lock,
2648 : .filesystem_sharemode_fn = vfs_gluster_filesystem_sharemode,
2649 : .fcntl_fn = vfs_gluster_fcntl,
2650 : .linux_setlease_fn = vfs_gluster_linux_setlease,
2651 : .getlock_fn = vfs_gluster_getlock,
2652 : .symlinkat_fn = vfs_gluster_symlinkat,
2653 : .readlinkat_fn = vfs_gluster_readlinkat,
2654 : .linkat_fn = vfs_gluster_linkat,
2655 : .mknodat_fn = vfs_gluster_mknodat,
2656 : .realpath_fn = vfs_gluster_realpath,
2657 : .fchflags_fn = vfs_gluster_fchflags,
2658 : .file_id_create_fn = NULL,
2659 : .fstreaminfo_fn = NULL,
2660 : .get_real_filename_at_fn = vfs_gluster_get_real_filename_at,
2661 : .connectpath_fn = vfs_gluster_connectpath,
2662 : .create_dfs_pathat_fn = vfs_gluster_create_dfs_pathat,
2663 : .read_dfs_pathat_fn = vfs_gluster_read_dfs_pathat,
2664 :
2665 : .brl_lock_windows_fn = NULL,
2666 : .brl_unlock_windows_fn = NULL,
2667 : .strict_lock_check_fn = NULL,
2668 : .translate_name_fn = NULL,
2669 : .fsctl_fn = NULL,
2670 :
2671 : /* NT ACL Operations */
2672 : .fget_nt_acl_fn = NULL,
2673 : .fset_nt_acl_fn = NULL,
2674 : .audit_file_fn = NULL,
2675 :
2676 : /* Posix ACL Operations */
2677 : .sys_acl_get_fd_fn = posixacl_xattr_acl_get_fd,
2678 : .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2679 : .sys_acl_set_fd_fn = posixacl_xattr_acl_set_fd,
2680 : .sys_acl_delete_def_fd_fn = posixacl_xattr_acl_delete_def_fd,
2681 :
2682 : /* EA Operations */
2683 : .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
2684 : .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
2685 : .fgetxattr_fn = vfs_gluster_fgetxattr,
2686 : .flistxattr_fn = vfs_gluster_flistxattr,
2687 : .fremovexattr_fn = vfs_gluster_fremovexattr,
2688 : .fsetxattr_fn = vfs_gluster_fsetxattr,
2689 :
2690 : /* AIO Operations */
2691 : .aio_force_fn = vfs_gluster_aio_force,
2692 :
2693 : /* Durable handle Operations */
2694 : .durable_cookie_fn = NULL,
2695 : .durable_disconnect_fn = NULL,
2696 : .durable_reconnect_fn = NULL,
2697 : };
2698 :
2699 : static_decl_vfs;
2700 26 : NTSTATUS vfs_glusterfs_init(TALLOC_CTX *ctx)
2701 : {
2702 26 : return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2703 : "glusterfs", &glusterfs_fns);
2704 : }
|