]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/samba/samba-3.6.23-glusterfs.patch
Merge branch 'core110'
[people/pmueller/ipfire-2.x.git] / src / patches / samba / samba-3.6.23-glusterfs.patch
1 From f2f684d4eadadeebf725b513bf4945ccf0aa7371 Mon Sep 17 00:00:00 2001
2 From: Anand Avati <avati@redhat.com>
3 Date: Wed, 29 May 2013 07:21:46 -0400
4 Subject: [PATCH 1/9] PATCHSET13: vfs_glusterfs: Samba VFS module for glusterfs
5
6 Implement a Samba VFS plugin for glusterfs based on gluster's gfapi.
7 This is a "bottom" vfs plugin (not something to be stacked on top of
8 another module), and translates (most) calls into closest actions
9 on gfapi.
10
11 Reviewed-by: Andrew Bartlett <abartlet@samba.org>
12 Reviewed-by: Simo Sorce <idra@samba.org>
13 Signed-off-by: Anand Avati <avati@redhat.com>
14 ---
15 source3/Makefile.in | 5 +
16 source3/configure.in | 23 +
17 source3/modules/vfs_glusterfs.c | 1461 +++++++++++++++++++++++++++++++++++++++
18 source3/modules/wscript_build | 9 +
19 source3/wscript | 22 +
20 5 files changed, 1520 insertions(+)
21 create mode 100644 source3/modules/vfs_glusterfs.c
22
23 diff --git a/source3/Makefile.in b/source3/Makefile.in
24 index 9e8e03d..27bc43e 100644
25 --- a/source3/Makefile.in
26 +++ b/source3/Makefile.in
27 @@ -848,6 +848,7 @@ VFS_SCANNEDONLY_OBJ = modules/vfs_scannedonly.o
28 VFS_CROSSRENAME_OBJ = modules/vfs_crossrename.o
29 VFS_LINUX_XFS_SGID_OBJ = modules/vfs_linux_xfs_sgid.o
30 VFS_TIME_AUDIT_OBJ = modules/vfs_time_audit.o
31 +VFS_GLUSTERFS_OBJ = modules/vfs_glusterfs.o
32
33 PAM_ERRORS_OBJ = ../libcli/auth/pam_errors.o
34 PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o $(PAM_ERRORS_OBJ)
35 @@ -3191,6 +3192,10 @@ bin/time_audit.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_TIME_AUDIT_OBJ)
36 @echo "Building plugin $@"
37 @$(SHLD_MODULE) $(VFS_TIME_AUDIT_OBJ)
38
39 +bin/glusterfs.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_GLUSTERFS_OBJ)
40 + @echo "Building plugin $@"
41 + $(SHLD_MODULE) $(VFS_GLUSTERFS_OBJ) @GLUSTERFS_LIBS@
42 +
43 #########################################################
44 ## IdMap NSS plugins
45
46 diff --git a/source3/configure.in b/source3/configure.in
47 index 42c23e3..3cc78e9 100644
48 --- a/source3/configure.in
49 +++ b/source3/configure.in
50 @@ -6688,6 +6688,29 @@
51 fi
52
53
54 +#############
55 +AC_ARG_ENABLE([glusterfs],
56 + AC_HELP_STRING([--disable-glusterfs],[Do not build vfs_glusterfs module]))
57 +
58 +GLUTERFS_LIBS=""
59 +
60 +if test "x$enable_glusterfs" != "xno"; then
61 + PKG_CHECK_MODULES([GLFS], [glusterfs-api >= 4], glfs_found=yes, glfs_found=no)
62 +fi
63 +
64 +if test "x$enable_glusterfs" = "xyes" -a "x$glfs_found" != "xyes"; then
65 + echo "GFAPI not found in build system"
66 + exit 1
67 +fi
68 +
69 +if test "x$glfs_found" = "xyes"; then
70 + CFLAGS="$CFLAGS $GLFS_CFLAGS"
71 + GLUSTERFS_LIBS="$GLFS_LIBS"
72 + default_shared_modules="$default_shared_modules vfs_glusterfs"
73 +fi
74 +AC_SUBST(GLUSTERFS_LIBS)
75 +
76 +
77 #################################################
78 # Set pthread stuff
79
80 @@ -7007,6 +7030,7 @@
81 SMB_MODULE(vfs_crossrename, \$(VFS_CROSSRENAME_OBJ), "bin/crossrename.$SHLIBEXT", VFS)
82 SMB_MODULE(vfs_linux_xfs_sgid, \$(VFS_LINUX_XFS_SGID_OBJ), "bin/linux_xfs_sgid.$SHLIBEXT", VFS)
83 SMB_MODULE(vfs_time_audit, \$(VFS_TIME_AUDIT_OBJ), "bin/time_audit.$SHLIBEXT", VFS)
84 +SMB_MODULE(vfs_glusterfs, \$(VFS_GLUSTERFS_OBJ), "bin/glusterfs.$SHLIBEXT", VFS)
85
86 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
87
88 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
89 new file mode 100644
90 index 0000000..4beac1d
91 --- /dev/null
92 +++ b/source3/modules/vfs_glusterfs.c
93 @@ -0,0 +1,1461 @@
94 +/*
95 + Unix SMB/CIFS implementation.
96 +
97 + Wrap GlusterFS GFAPI calls in vfs functions.
98 +
99 + Copyright (c) 2013 Anand Avati <avati@redhat.com>
100 +
101 + This program is free software; you can redistribute it and/or modify
102 + it under the terms of the GNU General Public License as published by
103 + the Free Software Foundation; either version 3 of the License, or
104 + (at your option) any later version.
105 +
106 + This program is distributed in the hope that it will be useful,
107 + but WITHOUT ANY WARRANTY; without even the implied warranty of
108 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109 + GNU General Public License for more details.
110 +
111 + You should have received a copy of the GNU General Public License
112 + along with this program. If not, see <http://www.gnu.org/licenses/>.
113 +*/
114 +
115 +#include "includes.h"
116 +#include "smbd/smbd.h"
117 +#include <stdio.h>
118 +#include "api/glfs.h"
119 +
120 +#define DEFAULT_VOLFILE_SERVER "localhost"
121 +
122 +/*
123 + TODO
124 + ----
125 + Short term:
126 + - AIO support
127 + - sendfile/recvfile support
128 +*/
129 +
130 +/* Helpers to provide 'integer' fds */
131 +
132 +/* This is global. gfapi's FD operations do not
133 + require filesystem context.
134 +*/
135 +static glfs_fd_t **glfd_fd;
136 +static int glfd_fd_size;
137 +static int glfd_fd_used;
138 +static int glfd_fd_store(glfs_fd_t *glfd)
139 +{
140 + int i;
141 + void *tmp;
142 +
143 + if (glfd_fd_size == glfd_fd_used) {
144 + if (glfd_fd_size >= INT_MAX - 1) {
145 + errno = ENOMEM;
146 + return -1;
147 + }
148 +
149 + tmp = talloc_realloc(glfd_fd, glfd_fd, glfs_fd_t *,
150 + glfd_fd_size + 1);
151 + if (tmp == NULL) {
152 + errno = ENOMEM;
153 + return -1;
154 + }
155 +
156 + glfd_fd = tmp;
157 + glfd_fd[glfd_fd_size] = 0;
158 + glfd_fd_size++;
159 + }
160 +
161 + for (i = 0; i < glfd_fd_size; i++) {
162 + if (!glfd_fd[i]) {
163 + break;
164 + }
165 + }
166 + glfd_fd_used++;
167 + glfd_fd[i] = glfd;
168 + return i;
169 +}
170 +
171 +static glfs_fd_t *glfd_fd_get(int i)
172 +{
173 + if (i < 0 || i >= glfd_fd_size) {
174 + return NULL;
175 + }
176 + return glfd_fd[i];
177 +}
178 +
179 +static glfs_fd_t *glfd_fd_clear(int i)
180 +{
181 + glfs_fd_t *glfd = NULL;
182 +
183 + if (i < 0 || i >= glfd_fd_size) {
184 + return NULL;
185 + }
186 +
187 + glfd = glfd_fd[i];
188 + glfd_fd[i] = 0;
189 + glfd_fd_used--;
190 + return glfd;
191 +}
192 +
193 +/* Helper to convert stat to stat_ex */
194 +
195 +static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src)
196 +{
197 + ZERO_STRUCTP(dst);
198 +
199 + dst->st_ex_dev = src->st_dev;
200 + dst->st_ex_ino = src->st_ino;
201 + dst->st_ex_mode = src->st_mode;
202 + dst->st_ex_nlink = src->st_nlink;
203 + dst->st_ex_uid = src->st_uid;
204 + dst->st_ex_gid = src->st_gid;
205 + dst->st_ex_rdev = src->st_rdev;
206 + dst->st_ex_size = src->st_size;
207 + dst->st_ex_atime.tv_sec = src->st_atime;
208 +#ifdef STAT_HAVE_NSEC
209 + dst->st_ex_atime.tv_nsec = src->st_atime_nsec;
210 +#endif
211 + dst->st_ex_mtime.tv_sec = src->st_mtime;
212 +#ifdef STAT_HAVE_NSEC
213 + dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec;
214 +#endif
215 + dst->st_ex_ctime.tv_sec = src->st_ctime;
216 +#ifdef STAT_HAVE_NSEC
217 + dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec;
218 +#endif
219 + dst->st_ex_btime.tv_sec = src->st_mtime;
220 +#ifdef STAT_HAVE_NSEC
221 + dst->st_ex_btime.tv_nsec = src->st_mtime_nsec;
222 +#endif
223 + dst->st_ex_blksize = src->st_blksize;
224 + dst->st_ex_blocks = src->st_blocks;
225 +}
226 +
227 +/* pre-opened glfs_t */
228 +
229 +static struct glfs_preopened {
230 + char *volume;
231 + glfs_t *fs;
232 + int ref;
233 + struct glfs_preopened *next, *prev;
234 +} *glfs_preopened;
235 +
236 +
237 +int glfs_set_preopened(const char *volume, glfs_t *fs)
238 +{
239 + struct glfs_preopened *entry = NULL;
240 +
241 + entry = talloc_zero(NULL, struct glfs_preopened);
242 + if (!entry) {
243 + errno = ENOMEM;
244 + return -1;
245 + }
246 +
247 + entry->volume = talloc_strdup(entry, volume);
248 + if (!entry->volume) {
249 + talloc_free(entry);
250 + errno = ENOMEM;
251 + return -1;
252 + }
253 +
254 + entry->fs = fs;
255 + entry->ref = 1;
256 +
257 + DLIST_ADD(glfs_preopened, entry);
258 +
259 + return 0;
260 +}
261 +
262 +static glfs_t *glfs_find_preopened(const char *volume)
263 +{
264 + struct glfs_preopened *entry = NULL;
265 +
266 + for (entry = glfs_preopened; entry; entry = entry->next) {
267 + if (strcmp(entry->volume, volume) == 0) {
268 + entry->ref++;
269 + return entry->fs;
270 + }
271 + }
272 +
273 + return NULL;
274 +}
275 +
276 +static void glfs_clear_preopened(glfs_t *fs)
277 +{
278 + int i;
279 + struct glfs_preopened *entry = NULL;
280 +
281 + for (entry = glfs_preopened; entry; entry = entry->next) {
282 + if (entry->fs == fs) {
283 + if (--entry->ref)
284 + return;
285 +
286 + DLIST_REMOVE(glfs_preopened, entry);
287 +
288 + glfs_fini(entry->fs);
289 + talloc_free(entry);
290 + }
291 + }
292 +}
293 +
294 +/* Disk Operations */
295 +
296 +static int vfs_gluster_connect(struct vfs_handle_struct *handle,
297 + const char *service, const char *user)
298 +{
299 + const char *volfile_server;
300 + const char *volume;
301 + const char *logfile;
302 + int loglevel;
303 + glfs_t *fs;
304 + int ret;
305 +
306 + logfile = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
307 + "logfile", NULL);
308 +
309 + loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1);
310 +
311 + volfile_server = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
312 + "volfile_server", NULL);
313 + if (volfile_server == NULL) {
314 + volfile_server = DEFAULT_VOLFILE_SERVER;
315 + }
316 +
317 + volume = lp_parm_const_string(SNUM(handle->conn), "glusterfs", "volume",
318 + NULL);
319 + if (volume == NULL) {
320 + volume = service;
321 + }
322 +
323 + fs = glfs_find_preopened(volume);
324 + if (fs) {
325 + goto found;
326 + }
327 +
328 + fs = glfs_new(volume);
329 + if (fs == NULL) {
330 + return -1;
331 + }
332 +
333 + ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 0);
334 + if (ret < 0) {
335 + DEBUG(0, ("Failed to set volfile_server %s\n", volfile_server));
336 + glfs_fini(fs);
337 + return -1;
338 + }
339 +
340 + ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl",
341 + "true");
342 + if (ret < 0) {
343 + DEBUG(0, ("%s: Failed to set xlator options\n", volume));
344 + glfs_fini(fs);
345 + return -1;
346 + }
347 +
348 + ret = glfs_set_logging(fs, logfile, loglevel);
349 + if (ret < 0) {
350 + DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n",
351 + volume, logfile, loglevel));
352 + glfs_fini(fs);
353 + return -1;
354 + }
355 +
356 + ret = glfs_init(fs);
357 + if (ret < 0) {
358 + DEBUG(0, ("%s: Failed to initialize volume (%s)\n",
359 + volume, strerror(errno)));
360 + glfs_fini(fs);
361 + return -1;
362 + }
363 +
364 + ret = glfs_set_preopened(volume, fs);
365 + if (ret < 0) {
366 + DEBUG(0, ("%s: Failed to register volume (%s)\n",
367 + volume, strerror(errno)));
368 + glfs_fini(fs);
369 + return -1;
370 + }
371 +found:
372 + DEBUG(0, ("%s: Initialized volume from server %s\n",
373 + volume, volfile_server));
374 + handle->data = fs;
375 + return 0;
376 +}
377 +
378 +static void vfs_gluster_disconnect(struct vfs_handle_struct *handle)
379 +{
380 + glfs_t *fs = NULL;
381 +
382 + fs = handle->data;
383 +
384 + glfs_clear_preopened(fs);
385 +}
386 +
387 +static uint64_t
388 +vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
389 + bool small_query, uint64_t *bsize_p, uint64_t *dfree_p,
390 + uint64_t *dsize_p)
391 +{
392 + struct statvfs statvfs = { 0, };
393 + uint64_t dfree = 0;
394 + int ret;
395 +
396 + ret = glfs_statvfs(handle->data, path, &statvfs);
397 + if (ret < 0) {
398 + DEBUG(0, ("glfs_statvfs(%s) failed: %s\n",
399 + path, strerror(errno)));
400 + return -1;
401 + }
402 +
403 + dfree = statvfs.f_bsize * statvfs.f_bavail;
404 +
405 + if (bsize_p) {
406 + *bsize_p = statvfs.f_bsize;
407 + }
408 + if (dfree_p) {
409 + *dfree_p = dfree;
410 + }
411 + if (dsize_p) {
412 + *dsize_p = statvfs.f_bsize * statvfs.f_blocks;
413 + }
414 +
415 + return dfree;
416 +}
417 +
418 +static int
419 +vfs_gluster_get_quota(struct vfs_handle_struct *handle,
420 + enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
421 +{
422 + errno = ENOSYS;
423 + return -1;
424 +}
425 +
426 +static int
427 +vfs_gluster_set_quota(struct vfs_handle_struct *handle,
428 + enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
429 +{
430 + errno = ENOSYS;
431 + return -1;
432 +}
433 +
434 +static int vfs_gluster_statvfs(struct vfs_handle_struct *handle,
435 + const char *path,
436 + struct vfs_statvfs_struct *vfs_statvfs)
437 +{
438 + struct statvfs statvfs = { 0, };
439 + int ret;
440 +
441 + ret = glfs_statvfs(handle->data, path, &statvfs);
442 + if (ret < 0) {
443 + DEBUG(0, ("glfs_statvfs(%s) failed: %s\n",
444 + path, strerror(errno)));
445 + return -1;
446 + }
447 +
448 + ZERO_STRUCTP(vfs_statvfs);
449 +
450 + vfs_statvfs->OptimalTransferSize = statvfs.f_frsize;
451 + vfs_statvfs->BlockSize = statvfs.f_bsize;
452 + vfs_statvfs->TotalBlocks = statvfs.f_blocks;
453 + vfs_statvfs->BlocksAvail = statvfs.f_bfree;
454 + vfs_statvfs->UserBlocksAvail = statvfs.f_bavail;
455 + vfs_statvfs->TotalFileNodes = statvfs.f_files;
456 + vfs_statvfs->FreeFileNodes = statvfs.f_ffree;
457 + vfs_statvfs->FsIdentifier = statvfs.f_fsid;
458 + vfs_statvfs->FsCapabilities =
459 + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
460 +
461 + return ret;
462 +}
463 +
464 +static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle,
465 + enum timestamp_set_resolution *p_ts_res)
466 +{
467 + uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
468 +
469 +#ifdef STAT_HAVE_NSEC
470 + *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
471 +#endif
472 +
473 + return caps;
474 +}
475 +
476 +static DIR *vfs_gluster_opendir(struct vfs_handle_struct *handle,
477 + const char *path, const char *mask,
478 + uint32 attributes)
479 +{
480 + glfs_fd_t *fd;
481 +
482 + fd = glfs_opendir(handle->data, path);
483 + if (fd == NULL) {
484 + DEBUG(0, ("glfs_opendir(%s) failed: %s\n",
485 + path, strerror(errno)));
486 + }
487 +
488 + return (DIR *) fd;
489 +}
490 +
491 +static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle,
492 + files_struct *fsp, const char *mask,
493 + uint32 attributes)
494 +{
495 + return (DIR *) glfd_fd_get(fsp->fh->fd);
496 +}
497 +
498 +static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp)
499 +{
500 + return glfs_closedir((void *)dirp);
501 +}
502 +
503 +static SMB_STRUCT_DIRENT *vfs_gluster_readdir(struct vfs_handle_struct *handle,
504 + SMB_STRUCT_DIR *dirp,
505 + SMB_STRUCT_STAT *sbuf)
506 +{
507 + char direntbuf[512];
508 + int ret;
509 + struct stat stat;
510 + struct dirent *dirent = 0;
511 + static SMB_STRUCT_DIRENT result;
512 +
513 + if (sbuf != NULL) {
514 + ret = glfs_readdirplus_r((void *)dirp, &stat, (void *)direntbuf,
515 + &dirent);
516 + } else {
517 + ret = glfs_readdir_r((void *)dirp, (void *)direntbuf, &dirent);
518 + }
519 +
520 + if (ret < 0 || (dirent == NULL)) {
521 + return NULL;
522 + }
523 +
524 + if (sbuf != NULL) {
525 + smb_stat_ex_from_stat(sbuf, &stat);
526 + }
527 +
528 + result.d_ino = dirent->d_ino;
529 + result.d_off = dirent->d_off;
530 + result.d_reclen = dirent->d_reclen;
531 + result.d_type = dirent->d_type;
532 + strncpy(result.d_name, dirent->d_name, 256);
533 +
534 + return &result;
535 +}
536 +
537 +static long vfs_gluster_telldir(struct vfs_handle_struct *handle, DIR *dirp)
538 +{
539 + return glfs_telldir((void *)dirp);
540 +}
541 +
542 +static void vfs_gluster_seekdir(struct vfs_handle_struct *handle, DIR *dirp,
543 + long offset)
544 +{
545 + glfs_seekdir((void *)dirp, offset);
546 +}
547 +
548 +static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle,
549 + DIR *dirp)
550 +{
551 + glfs_seekdir((void *)dirp, 0);
552 +}
553 +
554 +static void vfs_gluster_init_search_op(struct vfs_handle_struct *handle,
555 + DIR *dirp)
556 +{
557 + return;
558 +}
559 +
560 +static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, const char *path,
561 + mode_t mode)
562 +{
563 + return glfs_mkdir(handle->data, path, mode);
564 +}
565 +
566 +static int vfs_gluster_rmdir(struct vfs_handle_struct *handle, const char *path)
567 +{
568 + return glfs_rmdir(handle->data, path);
569 +}
570 +
571 +static int vfs_gluster_open(struct vfs_handle_struct *handle,
572 + struct smb_filename *smb_fname, files_struct *fsp,
573 + int flags, mode_t mode)
574 +{
575 + glfs_fd_t *glfd;
576 +
577 + if (flags & O_DIRECTORY) {
578 + glfd = glfs_opendir(handle->data, smb_fname->base_name);
579 + } else if (flags & O_CREAT) {
580 + glfd = glfs_creat(handle->data, smb_fname->base_name, flags,
581 + mode);
582 + } else {
583 + glfd = glfs_open(handle->data, smb_fname->base_name, flags);
584 + }
585 +
586 + if (glfd == NULL) {
587 + DEBUG(0, ("glfs_{open[dir],creat}(%s) failed: %s\n",
588 + smb_fname->base_name, strerror(errno)));
589 + return -1;
590 + }
591 +
592 + return glfd_fd_store(glfd);
593 +}
594 +
595 +static int vfs_gluster_close(struct vfs_handle_struct *handle,
596 + files_struct *fsp)
597 +{
598 + return glfs_close(glfd_fd_clear(fsp->fh->fd));
599 +}
600 +
601 +static ssize_t vfs_gluster_read(struct vfs_handle_struct *handle,
602 + files_struct *fsp, void *data, size_t n)
603 +{
604 + return glfs_read(glfd_fd_get(fsp->fh->fd), data, n, 0);
605 +}
606 +
607 +static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle,
608 + files_struct *fsp, void *data, size_t n,
609 + off_t offset)
610 +{
611 + return glfs_pread(glfd_fd_get(fsp->fh->fd), data, n, offset, 0);
612 +}
613 +
614 +static ssize_t vfs_gluster_write(struct vfs_handle_struct *handle,
615 + files_struct *fsp, const void *data, size_t n)
616 +{
617 + return glfs_write(glfd_fd_get(fsp->fh->fd), data, n, 0);
618 +}
619 +
620 +static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle,
621 + files_struct *fsp, const void *data, size_t n,
622 + off_t offset)
623 +{
624 + return glfs_pwrite(glfd_fd_get(fsp->fh->fd), data, n, offset, 0);
625 +}
626 +
627 +static off_t vfs_gluster_lseek(struct vfs_handle_struct *handle,
628 + files_struct *fsp, off_t offset, int whence)
629 +{
630 + return glfs_lseek(glfd_fd_get(fsp->fh->fd), offset, whence);
631 +}
632 +
633 +static ssize_t vfs_gluster_sendfile(struct vfs_handle_struct *handle, int tofd,
634 + files_struct *fromfsp, const DATA_BLOB *hdr,
635 + off_t offset, size_t n)
636 +{
637 + errno = ENOTSUP;
638 + return -1;
639 +}
640 +
641 +static ssize_t vfs_gluster_recvfile(struct vfs_handle_struct *handle,
642 + int fromfd, files_struct *tofsp,
643 + off_t offset, size_t n)
644 +{
645 + errno = ENOTSUP;
646 + return -1;
647 +}
648 +
649 +static int vfs_gluster_rename(struct vfs_handle_struct *handle,
650 + const struct smb_filename *smb_fname_src,
651 + const struct smb_filename *smb_fname_dst)
652 +{
653 + return glfs_rename(handle->data, smb_fname_src->base_name,
654 + smb_fname_dst->base_name);
655 +}
656 +
657 +static int vfs_gluster_fsync(struct vfs_handle_struct *handle,
658 + files_struct *fsp)
659 +{
660 + return glfs_fsync(glfd_fd_get(fsp->fh->fd));
661 +}
662 +
663 +static int vfs_gluster_stat(struct vfs_handle_struct *handle,
664 + struct smb_filename *smb_fname)
665 +{
666 + struct stat st;
667 + int ret;
668 +
669 + ret = glfs_stat(handle->data, smb_fname->base_name, &st);
670 + if (ret == 0) {
671 + smb_stat_ex_from_stat(&smb_fname->st, &st);
672 + }
673 + if (ret < 0 && errno != ENOENT) {
674 + DEBUG(0, ("glfs_stat(%s) failed: %s\n",
675 + smb_fname->base_name, strerror(errno)));
676 + }
677 + return ret;
678 +}
679 +
680 +static int vfs_gluster_fstat(struct vfs_handle_struct *handle,
681 + files_struct *fsp, SMB_STRUCT_STAT *sbuf)
682 +{
683 + struct stat st;
684 + int ret;
685 +
686 + ret = glfs_fstat(glfd_fd_get(fsp->fh->fd), &st);
687 + if (ret == 0) {
688 + smb_stat_ex_from_stat(sbuf, &st);
689 + }
690 + if (ret < 0) {
691 + DEBUG(0, ("glfs_ftat(%d) failed: %s\n",
692 + fsp->fh->fd, strerror(errno)));
693 + }
694 + return ret;
695 +}
696 +
697 +static int vfs_gluster_lstat(struct vfs_handle_struct *handle,
698 + struct smb_filename *smb_fname)
699 +{
700 + struct stat st;
701 + int ret;
702 +
703 + ret = glfs_lstat(handle->data, smb_fname->base_name, &st);
704 + if (ret == 0) {
705 + smb_stat_ex_from_stat(&smb_fname->st, &st);
706 + }
707 + if (ret < 0 && errno != ENOENT) {
708 + DEBUG(0, ("glfs_lstat(%s) failed: %s\n",
709 + smb_fname->base_name, strerror(errno)));
710 + }
711 +
712 + return ret;
713 +}
714 +
715 +static uint64_t vfs_gluster_get_alloc_size(struct vfs_handle_struct *handle,
716 + files_struct *fsp,
717 + const SMB_STRUCT_STAT *sbuf)
718 +{
719 + return sbuf->st_ex_blocks * 512;
720 +}
721 +
722 +static int vfs_gluster_unlink(struct vfs_handle_struct *handle,
723 + const struct smb_filename *smb_fname)
724 +{
725 + return glfs_unlink(handle->data, smb_fname->base_name);
726 +}
727 +
728 +static int vfs_gluster_chmod(struct vfs_handle_struct *handle,
729 + const char *path, mode_t mode)
730 +{
731 + return glfs_chmod(handle->data, path, mode);
732 +}
733 +
734 +static int vfs_gluster_fchmod(struct vfs_handle_struct *handle,
735 + files_struct *fsp, mode_t mode)
736 +{
737 + return glfs_fchmod(glfd_fd_get(fsp->fh->fd), mode);
738 +}
739 +
740 +static int vfs_gluster_chown(struct vfs_handle_struct *handle,
741 + const char *path, uid_t uid, gid_t gid)
742 +{
743 + return glfs_chown(handle->data, path, uid, gid);
744 +}
745 +
746 +static int vfs_gluster_fchown(struct vfs_handle_struct *handle,
747 + files_struct *fsp, uid_t uid, gid_t gid)
748 +{
749 + return glfs_fchown(glfd_fd_get(fsp->fh->fd), uid, gid);
750 +}
751 +
752 +static int vfs_gluster_lchown(struct vfs_handle_struct *handle,
753 + const char *path, uid_t uid, gid_t gid)
754 +{
755 + return glfs_lchown(handle->data, path, uid, gid);
756 +}
757 +
758 +static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const char *path)
759 +{
760 + return glfs_chdir(handle->data, path);
761 +}
762 +
763 +static char *vfs_gluster_getwd(struct vfs_handle_struct *handle, char *path)
764 +{
765 + return glfs_getcwd(handle->data, path, PATH_MAX);
766 +}
767 +
768 +static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
769 + const struct smb_filename *smb_fname,
770 + struct smb_file_time *ft)
771 +{
772 + struct timespec times[2];
773 +
774 + times[0].tv_sec = ft->atime.tv_sec;
775 + times[0].tv_nsec = ft->atime.tv_nsec;
776 + times[1].tv_sec = ft->mtime.tv_sec;
777 + times[1].tv_nsec = ft->mtime.tv_nsec;
778 +
779 + return glfs_utimens(handle->data, smb_fname->base_name, times);
780 +}
781 +
782 +static int vfs_gluster_ftruncate(struct vfs_handle_struct *handle,
783 + files_struct *fsp, off_t offset)
784 +{
785 + return glfs_ftruncate(glfd_fd_get(fsp->fh->fd), offset);
786 +}
787 +
788 +static int vfs_gluster_fallocate(struct vfs_handle_struct *handle,
789 + struct files_struct *fsp,
790 + enum vfs_fallocate_mode mode,
791 + off_t offset, off_t len)
792 +{
793 + errno = ENOTSUP;
794 + return -1;
795 +}
796 +
797 +static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
798 + const char *path)
799 +{
800 + return glfs_realpath(handle->data, path, 0);
801 +}
802 +
803 +static bool vfs_gluster_lock(struct vfs_handle_struct *handle,
804 + files_struct *fsp, int op, off_t offset,
805 + off_t count, int type)
806 +{
807 + struct flock flock = { 0, };
808 + int ret;
809 +
810 + flock.l_type = type;
811 + flock.l_whence = SEEK_SET;
812 + flock.l_start = offset;
813 + flock.l_len = count;
814 + flock.l_pid = 0;
815 +
816 + ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), op, &flock);
817 +
818 + if (op == F_GETLK) {
819 + /* lock query, true if someone else has locked */
820 + if ((ret != -1) &&
821 + (flock.l_type != F_UNLCK) &&
822 + (flock.l_pid != 0) && (flock.l_pid != getpid()))
823 + return true;
824 + /* not me */
825 + return false;
826 + }
827 +
828 + if (ret == -1) {
829 + return false;
830 + }
831 +
832 + return true;
833 +}
834 +
835 +static int vfs_gluster_kernel_flock(struct vfs_handle_struct *handle,
836 + files_struct *fsp, uint32 share_mode,
837 + uint32_t access_mask)
838 +{
839 + return 0;
840 +}
841 +
842 +static int vfs_gluster_linux_setlease(struct vfs_handle_struct *handle,
843 + files_struct *fsp, int leasetype)
844 +{
845 + errno = ENOSYS;
846 + return -1;
847 +}
848 +
849 +static bool vfs_gluster_getlock(struct vfs_handle_struct *handle,
850 + files_struct *fsp, off_t *poffset,
851 + off_t *pcount, int *ptype, pid_t *ppid)
852 +{
853 + struct flock flock = { 0, };
854 + int ret;
855 +
856 + flock.l_type = *ptype;
857 + flock.l_whence = SEEK_SET;
858 + flock.l_start = *poffset;
859 + flock.l_len = *pcount;
860 + flock.l_pid = 0;
861 +
862 + ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), F_GETLK, &flock);
863 +
864 + if (ret == -1) {
865 + return false;
866 + }
867 +
868 + *ptype = flock.l_type;
869 + *poffset = flock.l_start;
870 + *pcount = flock.l_len;
871 + *ppid = flock.l_pid;
872 +
873 + return true;
874 +}
875 +
876 +static int vfs_gluster_symlink(struct vfs_handle_struct *handle,
877 + const char *oldpath, const char *newpath)
878 +{
879 + return glfs_symlink(handle->data, oldpath, newpath);
880 +}
881 +
882 +static int vfs_gluster_readlink(struct vfs_handle_struct *handle,
883 + const char *path, char *buf, size_t bufsiz)
884 +{
885 + return glfs_readlink(handle->data, path, buf, bufsiz);
886 +}
887 +
888 +static int vfs_gluster_link(struct vfs_handle_struct *handle,
889 + const char *oldpath, const char *newpath)
890 +{
891 + return glfs_link(handle->data, oldpath, newpath);
892 +}
893 +
894 +static int vfs_gluster_mknod(struct vfs_handle_struct *handle, const char *path,
895 + mode_t mode, SMB_DEV_T dev)
896 +{
897 + return glfs_mknod(handle->data, path, mode, dev);
898 +}
899 +
900 +static NTSTATUS vfs_gluster_notify_watch(struct vfs_handle_struct *vfs_handle,
901 + struct sys_notify_context *ctx,
902 + struct notify_entry *e,
903 + void (*callback) (struct sys_notify_context *ctx,
904 + void *private_data,
905 + struct notify_event *ev),
906 + void *private_data, void *handle)
907 +{
908 + return NT_STATUS_NOT_IMPLEMENTED;
909 +}
910 +
911 +static int vfs_gluster_chflags(struct vfs_handle_struct *handle,
912 + const char *path, unsigned int flags)
913 +{
914 + errno = ENOSYS;
915 + return -1;
916 +}
917 +
918 +static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle,
919 + const char *path, const char *name,
920 + TALLOC_CTX *mem_ctx, char **found_name)
921 +{
922 + int ret;
923 + char key_buf[NAME_MAX + 64];
924 + char val_buf[NAME_MAX + 1];
925 +
926 + if (strlen(name) >= NAME_MAX) {
927 + errno = ENAMETOOLONG;
928 + return -1;
929 + }
930 +
931 + snprintf(key_buf, NAME_MAX + 64,
932 + "user.glusterfs.get_real_filename:%s", name);
933 +
934 + ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1);
935 + if (ret == -1 && errno == ENODATA) {
936 + errno = EOPNOTSUPP;
937 + return -1;
938 + }
939 +
940 + *found_name = talloc_strdup(mem_ctx, val_buf);
941 + if (found_name[0] == NULL) {
942 + errno = ENOMEM;
943 + return -1;
944 + }
945 + return 0;
946 +}
947 +
948 +static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle,
949 + const char *filename)
950 +{
951 + return handle->conn->connectpath;
952 +}
953 +
954 +/* EA Operations */
955 +
956 +static ssize_t vfs_gluster_getxattr(struct vfs_handle_struct *handle,
957 + const char *path, const char *name,
958 + void *value, size_t size)
959 +{
960 + return glfs_getxattr(handle->data, path, name, value, size);
961 +}
962 +
963 +static ssize_t vfs_gluster_lgetxattr(struct vfs_handle_struct *handle,
964 + const char *path, const char *name,
965 + void *value, size_t size)
966 +{
967 + return glfs_lgetxattr(handle->data, path, name, value, size);
968 +}
969 +
970 +static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle,
971 + files_struct *fsp, const char *name,
972 + void *value, size_t size)
973 +{
974 + return glfs_fgetxattr(glfd_fd_get(fsp->fh->fd), name, value, size);
975 +}
976 +
977 +static ssize_t vfs_gluster_listxattr(struct vfs_handle_struct *handle,
978 + const char *path, char *list, size_t size)
979 +{
980 + return glfs_listxattr(handle->data, path, list, size);
981 +}
982 +
983 +static ssize_t vfs_gluster_llistxattr(struct vfs_handle_struct *handle,
984 + const char *path, char *list, size_t size)
985 +{
986 + return glfs_llistxattr(handle->data, path, list, size);
987 +}
988 +
989 +static ssize_t vfs_gluster_flistxattr(struct vfs_handle_struct *handle,
990 + files_struct *fsp, char *list,
991 + size_t size)
992 +{
993 + return glfs_flistxattr(glfd_fd_get(fsp->fh->fd), list, size);
994 +}
995 +
996 +static int vfs_gluster_removexattr(struct vfs_handle_struct *handle,
997 + const char *path, const char *name)
998 +{
999 + return glfs_removexattr(handle->data, path, name);
1000 +}
1001 +
1002 +static int vfs_gluster_lremovexattr(struct vfs_handle_struct *handle,
1003 + const char *path, const char *name)
1004 +{
1005 + return glfs_lremovexattr(handle->data, path, name);
1006 +}
1007 +
1008 +static int vfs_gluster_fremovexattr(struct vfs_handle_struct *handle,
1009 + files_struct *fsp, const char *name)
1010 +{
1011 + return glfs_fremovexattr(glfd_fd_get(fsp->fh->fd), name);
1012 +}
1013 +
1014 +static int vfs_gluster_setxattr(struct vfs_handle_struct *handle,
1015 + const char *path, const char *name,
1016 + const void *value, size_t size, int flags)
1017 +{
1018 + return glfs_setxattr(handle->data, path, name, value, size, flags);
1019 +}
1020 +
1021 +static int vfs_gluster_lsetxattr(struct vfs_handle_struct *handle,
1022 + const char *path, const char *name,
1023 + const void *value, size_t size, int flags)
1024 +{
1025 + return glfs_lsetxattr(handle->data, path, name, value, size, flags);
1026 +}
1027 +
1028 +static int vfs_gluster_fsetxattr(struct vfs_handle_struct *handle,
1029 + files_struct *fsp, const char *name,
1030 + const void *value, size_t size, int flags)
1031 +{
1032 + return glfs_fsetxattr(glfd_fd_get(fsp->fh->fd), name, value, size,
1033 + flags);
1034 +}
1035 +
1036 +/* AIO Operations */
1037 +
1038 +static bool vfs_gluster_aio_force(struct vfs_handle_struct *handle,
1039 + files_struct *fsp)
1040 +{
1041 + return false;
1042 +}
1043 +
1044 +/* Offline Operations */
1045 +
1046 +static bool vfs_gluster_is_offline(struct vfs_handle_struct *handle,
1047 + const struct smb_filename *fname,
1048 + SMB_STRUCT_STAT *sbuf)
1049 +{
1050 + return false;
1051 +}
1052 +
1053 +static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
1054 + const struct smb_filename *fname)
1055 +{
1056 + errno = ENOTSUP;
1057 + return -1;
1058 +}
1059 +
1060 +/* Posix ACL Operations */
1061 +
1062 +#define GLUSTER_ACL_VERSION 2
1063 +#define GLUSTER_ACL_READ 0x04
1064 +#define GLUSTER_ACL_WRITE 0x02
1065 +#define GLUSTER_ACL_EXECUTE 0x01
1066 +
1067 +#define GLUSTER_ACL_UNDEFINED_TAG 0x00
1068 +#define GLUSTER_ACL_USER_OBJ 0x01
1069 +#define GLUSTER_ACL_USER 0x02
1070 +#define GLUSTER_ACL_GROUP_OBJ 0x04
1071 +#define GLUSTER_ACL_GROUP 0x08
1072 +#define GLUSTER_ACL_MASK 0x10
1073 +#define GLUSTER_ACL_OTHER 0x20
1074 +
1075 +#define GLUSTER_ACL_UNDEFINED_ID (-1)
1076 +
1077 +struct gluster_ace {
1078 + uint16_t tag;
1079 + uint16_t perm;
1080 + uint32_t id;
1081 +};
1082 +
1083 +struct gluster_acl_header {
1084 + uint32_t version;
1085 + struct gluster_ace entries[];
1086 +};
1087 +
1088 +static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1089 +{
1090 + int count;
1091 + size_t size;
1092 + struct gluster_ace *ace;
1093 + struct smb_acl_entry *smb_ace;
1094 + struct gluster_acl_header *hdr;
1095 + struct smb_acl_t *result;
1096 + int i;
1097 + uint16_t tag;
1098 + uint16_t perm;
1099 + uint32_t id;
1100 +
1101 + size = xattr_size;
1102 +
1103 + if (size < sizeof(*hdr)) {
1104 + /* ACL should be at least as big as the header */
1105 + errno = EINVAL;
1106 + return NULL;
1107 + }
1108 +
1109 + size -= sizeof(*hdr);
1110 +
1111 + if (size % sizeof(*ace)) {
1112 + /* Size of entries must strictly be a multiple of
1113 + size of an ACE
1114 + */
1115 + errno = EINVAL;
1116 + return NULL;
1117 + }
1118 +
1119 + count = size / sizeof(*ace);
1120 +
1121 + hdr = (void *)buf;
1122 +
1123 + if (ntohl(hdr->version) != GLUSTER_ACL_VERSION) {
1124 + DEBUG(0, ("Unknown gluster ACL version: %d\n",
1125 + ntohl(hdr->version)));
1126 + return NULL;
1127 + }
1128 +
1129 + result = SMB_MALLOC(sizeof(struct smb_acl_t) + (sizeof(struct smb_acl_entry) * count));
1130 + if (!result) {
1131 + errno = ENOMEM;
1132 + return NULL;
1133 + }
1134 +
1135 + result->count = count;
1136 +
1137 + smb_ace = result->acl;
1138 + ace = hdr->entries;
1139 +
1140 + for (i = 0; i < count; i++) {
1141 + tag = ntohs(ace->tag);
1142 +
1143 + switch(tag) {
1144 + case GLUSTER_ACL_USER:
1145 + smb_ace->a_type = SMB_ACL_USER;
1146 + break;
1147 + case GLUSTER_ACL_USER_OBJ:
1148 + smb_ace->a_type = SMB_ACL_USER_OBJ;
1149 + break;
1150 + case GLUSTER_ACL_GROUP:
1151 + smb_ace->a_type = SMB_ACL_GROUP;
1152 + break;
1153 + case GLUSTER_ACL_GROUP_OBJ:
1154 + smb_ace->a_type = SMB_ACL_GROUP_OBJ;
1155 + break;
1156 + case GLUSTER_ACL_OTHER:
1157 + smb_ace->a_type = SMB_ACL_OTHER;
1158 + break;
1159 + case GLUSTER_ACL_MASK:
1160 + smb_ace->a_type = SMB_ACL_MASK;
1161 + break;
1162 + default:
1163 + DEBUG(0, ("unknown tag type %d\n", (unsigned int) tag));
1164 + return NULL;
1165 + }
1166 +
1167 + id = ntohl(ace->id);
1168 +
1169 + switch(smb_ace->a_type) {
1170 + case SMB_ACL_USER:
1171 + smb_ace->uid = id;
1172 + break;
1173 + case SMB_ACL_GROUP:
1174 + smb_ace->gid = id;
1175 + break;
1176 + default:
1177 + break;
1178 + }
1179 +
1180 + perm = ntohs(ace->perm);
1181 +
1182 + smb_ace->a_perm = 0;
1183 + smb_ace->a_perm |=
1184 + ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0);
1185 + smb_ace->a_perm |=
1186 + ((perm & GLUSTER_ACL_WRITE) ? SMB_ACL_WRITE : 0);
1187 + smb_ace->a_perm |=
1188 + ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
1189 +
1190 + ace++;
1191 + smb_ace++;
1192 + }
1193 +
1194 + return result;
1195 +}
1196 +
1197 +static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
1198 +{
1199 + ssize_t size;
1200 + struct gluster_ace *ace;
1201 + struct smb_acl_entry *smb_ace;
1202 + struct gluster_acl_header *hdr;
1203 + int i;
1204 + int count;
1205 + uint16_t tag;
1206 + uint16_t perm;
1207 + uint32_t id;
1208 +
1209 + count = theacl->count;
1210 +
1211 + size = sizeof(*hdr) + (count * sizeof(*ace));
1212 + if (!buf) {
1213 + return size;
1214 + }
1215 +
1216 + if (len < size) {
1217 + errno = ERANGE;
1218 + return -1;
1219 + }
1220 +
1221 + hdr = (void *)buf;
1222 + ace = hdr->entries;
1223 + smb_ace = theacl->acl;
1224 +
1225 + hdr->version = htonl(GLUSTER_ACL_VERSION);
1226 +
1227 + for (i = 0; i < count; i++) {
1228 + switch(smb_ace->a_type) {
1229 + case SMB_ACL_USER:
1230 + tag = GLUSTER_ACL_USER;
1231 + break;
1232 + case SMB_ACL_USER_OBJ:
1233 + tag = GLUSTER_ACL_USER_OBJ;
1234 + break;
1235 + case SMB_ACL_GROUP:
1236 + tag = GLUSTER_ACL_GROUP;
1237 + break;
1238 + case SMB_ACL_GROUP_OBJ:
1239 + tag = GLUSTER_ACL_GROUP_OBJ;
1240 + break;
1241 + case SMB_ACL_OTHER:
1242 + tag = GLUSTER_ACL_OTHER;
1243 + break;
1244 + case SMB_ACL_MASK:
1245 + tag = GLUSTER_ACL_MASK;
1246 + break;
1247 + default:
1248 + DEBUG(0, ("Unknown tag value %d\n",
1249 + smb_ace->a_type));
1250 + errno = EINVAL;
1251 + return -1;
1252 + }
1253 +
1254 + ace->tag = ntohs(tag);
1255 +
1256 + switch(smb_ace->a_type) {
1257 + case SMB_ACL_USER:
1258 + id = smb_ace->uid;
1259 + break;
1260 + case SMB_ACL_GROUP:
1261 + id = smb_ace->gid;
1262 + break;
1263 + default:
1264 + id = GLUSTER_ACL_UNDEFINED_ID;
1265 + break;
1266 + }
1267 +
1268 + ace->id = ntohl(id);
1269 +
1270 + ace->perm = 0;
1271 + ace->perm |=
1272 + ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
1273 + ace->perm |=
1274 + ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
1275 + ace->perm |=
1276 + ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
1277 +
1278 + ace++;
1279 + smb_ace++;
1280 + }
1281 +
1282 + return size;
1283 +}
1284 +
1285 +
1286 +static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle,
1287 + const char *path_p,
1288 + SMB_ACL_TYPE_T type)
1289 +{
1290 + struct smb_acl_t *result;
1291 + char *buf;
1292 + char *key;
1293 + ssize_t ret;
1294 +
1295 + switch (type) {
1296 + case SMB_ACL_TYPE_ACCESS:
1297 + key = "system.posix_acl_access";
1298 + break;
1299 + case SMB_ACL_TYPE_DEFAULT:
1300 + key = "system.posix_acl_default";
1301 + break;
1302 + default:
1303 + errno = EINVAL;
1304 + return NULL;
1305 + }
1306 +
1307 + ret = glfs_getxattr(handle->data, path_p, key, 0, 0);
1308 + if (ret <= 0) {
1309 + return NULL;
1310 + }
1311 +
1312 + buf = alloca(ret);
1313 + ret = glfs_getxattr(handle->data, path_p, key, buf, ret);
1314 + if (ret <= 0) {
1315 + return NULL;
1316 + }
1317 +
1318 + result = gluster_to_smb_acl(buf, ret);
1319 +
1320 + return result;
1321 +}
1322 +
1323 +static SMB_ACL_T vfs_gluster_sys_acl_get_fd(struct vfs_handle_struct *handle,
1324 + struct files_struct *fsp)
1325 +{
1326 + struct smb_acl_t *result;
1327 + int ret;
1328 + char *buf;
1329 +
1330 + ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd),
1331 + "system.posix_acl_access", 0, 0);
1332 + if (ret <= 0) {
1333 + return NULL;
1334 + }
1335 +
1336 + buf = alloca(ret);
1337 + ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd),
1338 + "system.posix_acl_access", buf, ret);
1339 + if (ret <= 0) {
1340 + return NULL;
1341 + }
1342 +
1343 + result = gluster_to_smb_acl(buf, ret);
1344 +
1345 + return result;
1346 +}
1347 +
1348 +static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle,
1349 + const char *name,
1350 + SMB_ACL_TYPE_T acltype,
1351 + SMB_ACL_T theacl)
1352 +{
1353 + int ret;
1354 + char *key;
1355 + char *buf;
1356 + ssize_t size;
1357 +
1358 + switch (acltype) {
1359 + case SMB_ACL_TYPE_ACCESS:
1360 + key = "system.posix_acl_access";
1361 + break;
1362 + case SMB_ACL_TYPE_DEFAULT:
1363 + key = "system.posix_acl_default";
1364 + break;
1365 + default:
1366 + errno = EINVAL;
1367 + return -1;
1368 + }
1369 +
1370 + size = smb_to_gluster_acl(theacl, 0, 0);
1371 + buf = alloca(size);
1372 +
1373 + size = smb_to_gluster_acl(theacl, buf, size);
1374 + if (size == -1) {
1375 + return -1;
1376 + }
1377 +
1378 + ret = glfs_setxattr(handle->data, name, key, buf, size, 0);
1379 +
1380 + return ret;
1381 +}
1382 +
1383 +static int vfs_gluster_sys_acl_set_fd(struct vfs_handle_struct *handle,
1384 + struct files_struct *fsp,
1385 + SMB_ACL_T theacl)
1386 +{
1387 + int ret;
1388 + char *buf;
1389 + ssize_t size;
1390 +
1391 + size = smb_to_gluster_acl(theacl, 0, 0);
1392 + buf = alloca(size);
1393 +
1394 + size = smb_to_gluster_acl(theacl, buf, size);
1395 + if (size == -1) {
1396 + return -1;
1397 + }
1398 +
1399 + ret = glfs_fsetxattr(glfd_fd_get(fsp->fh->fd),
1400 + "system.posix_acl_access", buf, size, 0);
1401 + return ret;
1402 +}
1403 +
1404 +static int vfs_gluster_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
1405 + const char *path)
1406 +{
1407 + return glfs_removexattr(handle->data, path, "system.posix_acl_default");
1408 +}
1409 +
1410 +static struct vfs_fn_pointers glusterfs_fns = {
1411 +
1412 + /* Disk Operations */
1413 +
1414 + .connect_fn = vfs_gluster_connect,
1415 + .disconnect = vfs_gluster_disconnect,
1416 + .disk_free = vfs_gluster_disk_free,
1417 + .get_quota = vfs_gluster_get_quota,
1418 + .set_quota = vfs_gluster_set_quota,
1419 + .statvfs = vfs_gluster_statvfs,
1420 + .fs_capabilities = vfs_gluster_fs_capabilities,
1421 +
1422 + /* Directory Operations */
1423 +
1424 + .opendir = vfs_gluster_opendir,
1425 + .fdopendir = vfs_gluster_fdopendir,
1426 + .readdir = vfs_gluster_readdir,
1427 + .seekdir = vfs_gluster_seekdir,
1428 + .telldir = vfs_gluster_telldir,
1429 + .rewind_dir = vfs_gluster_rewinddir,
1430 + .mkdir = vfs_gluster_mkdir,
1431 + .rmdir = vfs_gluster_rmdir,
1432 + .closedir = vfs_gluster_closedir,
1433 + .init_search_op = vfs_gluster_init_search_op,
1434 +
1435 + /* File Operations */
1436 +
1437 + .open_fn = vfs_gluster_open,
1438 + .create_file = NULL,
1439 + .close_fn = vfs_gluster_close,
1440 + .vfs_read = vfs_gluster_read,
1441 + .pread = vfs_gluster_pread,
1442 + .write = vfs_gluster_write,
1443 + .pwrite = vfs_gluster_pwrite,
1444 + .lseek = vfs_gluster_lseek,
1445 + .sendfile = vfs_gluster_sendfile,
1446 + .recvfile = vfs_gluster_recvfile,
1447 + .rename = vfs_gluster_rename,
1448 + .fsync = vfs_gluster_fsync,
1449 + .stat = vfs_gluster_stat,
1450 + .fstat = vfs_gluster_fstat,
1451 + .lstat = vfs_gluster_lstat,
1452 + .get_alloc_size = vfs_gluster_get_alloc_size,
1453 + .unlink = vfs_gluster_unlink,
1454 +
1455 + .chmod = vfs_gluster_chmod,
1456 + .fchmod = vfs_gluster_fchmod,
1457 + .chown = vfs_gluster_chown,
1458 + .fchown = vfs_gluster_fchown,
1459 + .lchown = vfs_gluster_lchown,
1460 + .chdir = vfs_gluster_chdir,
1461 + .getwd = vfs_gluster_getwd,
1462 + .ntimes = vfs_gluster_ntimes,
1463 + .ftruncate = vfs_gluster_ftruncate,
1464 + .fallocate = vfs_gluster_fallocate,
1465 + .lock = vfs_gluster_lock,
1466 + .kernel_flock = vfs_gluster_kernel_flock,
1467 + .linux_setlease = vfs_gluster_linux_setlease,
1468 + .getlock = vfs_gluster_getlock,
1469 + .symlink = vfs_gluster_symlink,
1470 + .vfs_readlink = vfs_gluster_readlink,
1471 + .link = vfs_gluster_link,
1472 + .mknod = vfs_gluster_mknod,
1473 + .realpath = vfs_gluster_realpath,
1474 + .notify_watch = vfs_gluster_notify_watch,
1475 + .chflags = vfs_gluster_chflags,
1476 + .file_id_create = NULL,
1477 + .streaminfo = NULL,
1478 + .get_real_filename = vfs_gluster_get_real_filename,
1479 + .connectpath = vfs_gluster_connectpath,
1480 +
1481 + .brl_lock_windows = NULL,
1482 + .brl_unlock_windows = NULL,
1483 + .brl_cancel_windows = NULL,
1484 + .strict_lock = NULL,
1485 + .strict_unlock = NULL,
1486 + .translate_name = NULL,
1487 +
1488 + /* NT ACL Operations */
1489 + .fget_nt_acl = NULL,
1490 + .get_nt_acl = NULL,
1491 + .fset_nt_acl = NULL,
1492 +
1493 + /* Posix ACL Operations */
1494 + .chmod_acl = NULL, /* passthrough to default */
1495 + .fchmod_acl = NULL, /* passthrough to default */
1496 +
1497 + .sys_acl_get_entry = NULL,
1498 + .sys_acl_get_tag_type = NULL,
1499 + .sys_acl_get_permset = NULL,
1500 + .sys_acl_get_qualifier = NULL,
1501 + .sys_acl_get_file = vfs_gluster_sys_acl_get_file,
1502 + .sys_acl_get_fd = vfs_gluster_sys_acl_get_fd,
1503 + .sys_acl_clear_perms = NULL,
1504 + .sys_acl_add_perm = NULL,
1505 + .sys_acl_to_text = NULL,
1506 + .sys_acl_init = NULL,
1507 + .sys_acl_create_entry = NULL,
1508 + .sys_acl_set_tag_type = NULL,
1509 + .sys_acl_set_qualifier = NULL,
1510 + .sys_acl_set_permset = NULL,
1511 + .sys_acl_valid = NULL,
1512 + .sys_acl_set_file = vfs_gluster_sys_acl_set_file,
1513 + .sys_acl_set_fd = vfs_gluster_sys_acl_set_fd,
1514 + .sys_acl_delete_def_file = vfs_gluster_sys_acl_delete_def_file,
1515 + .sys_acl_get_perm = NULL,
1516 + .sys_acl_free_text = NULL,
1517 + .sys_acl_free_acl = NULL,
1518 + .sys_acl_free_qualifier = NULL,
1519 +
1520 + /* EA Operations */
1521 + .getxattr = vfs_gluster_getxattr,
1522 + .lgetxattr = vfs_gluster_lgetxattr,
1523 + .fgetxattr = vfs_gluster_fgetxattr,
1524 + .listxattr = vfs_gluster_listxattr,
1525 + .llistxattr = vfs_gluster_llistxattr,
1526 + .flistxattr = vfs_gluster_flistxattr,
1527 + .removexattr = vfs_gluster_removexattr,
1528 + .lremovexattr = vfs_gluster_lremovexattr,
1529 + .fremovexattr = vfs_gluster_fremovexattr,
1530 + .setxattr = vfs_gluster_setxattr,
1531 + .lsetxattr = vfs_gluster_lsetxattr,
1532 + .fsetxattr = vfs_gluster_fsetxattr,
1533 +
1534 + /* AIO Operations */
1535 + .aio_read = NULL,
1536 + .aio_write = NULL,
1537 + .aio_return_fn = NULL,
1538 + .aio_cancel = NULL,
1539 + .aio_error_fn = NULL,
1540 + .aio_fsync = NULL,
1541 + .aio_suspend = NULL,
1542 + .aio_force = vfs_gluster_aio_force,
1543 +
1544 + /* Offline Operations */
1545 + .is_offline = vfs_gluster_is_offline,
1546 + .set_offline = vfs_gluster_set_offline,
1547 +};
1548 +
1549 +NTSTATUS vfs_glusterfs_init(void);
1550 +NTSTATUS vfs_glusterfs_init(void)
1551 +{
1552 + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1553 + "glusterfs", &glusterfs_fns);
1554 +}
1555 diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
1556 index ff7163f..31c93be 100644
1557 --- a/source3/modules/wscript_build
1558 +++ b/source3/modules/wscript_build
1559 @@ -50,6 +50,7 @@ VFS_SCANNEDONLY_SRC = 'vfs_scannedonly.c'
1560 VFS_CROSSRENAME_SRC = 'vfs_crossrename.c'
1561 VFS_LINUX_XFS_SGID_SRC = 'vfs_linux_xfs_sgid.c'
1562 VFS_TIME_AUDIT_SRC = 'vfs_time_audit.c'
1563 +VFS_GLUSTERFS_SRC = 'vfs_glusterfs.c'
1564
1565
1566 bld.SAMBA3_SUBSYSTEM('NFS4_ACLS',
1567 @@ -408,6 +409,14 @@ bld.SAMBA3_MODULE('vfs_time_audit',
1568 internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_time_audit'),
1569 enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_time_audit'))
1570
1571 +bld.SAMBA3_MODULE('vfs_glusterfs',
1572 + subsystem='vfs',
1573 + source=VFS_GLUSTERFS_SRC,
1574 + deps='samba-util gfapi',
1575 + init_function='',
1576 + internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_glusterfs'),
1577 + enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_glusterfs'),
1578 + allow_undefined_symbols=False)
1579
1580
1581 CHARSET_WEIRD_SRC = 'weird.c'
1582 diff --git a/source3/wscript b/source3/wscript
1583 index bcc6ce1..7e34db5 100644
1584 --- a/source3/wscript
1585 +++ b/source3/wscript
1586 @@ -60,6 +60,7 @@ def set_options(opt):
1587 opt.SAMBA3_ADD_OPTION('automount')
1588 opt.SAMBA3_ADD_OPTION('aio-support')
1589 opt.SAMBA3_ADD_OPTION('profiling-data')
1590 + opt.SAMBA3_ADD_OPTION('glusterfs', with_name="enable", without_name="disable", default=True)
1591
1592 opt.SAMBA3_ADD_OPTION('cluster-support')
1593
1594 @@ -1701,6 +1702,24 @@ main() {
1595 conf.undefine('CLUSTER_SUPPORT')
1596
1597
1598 + #
1599 + # Checking for GlusterFS
1600 + #
1601 + if Options.options.with_glusterfs:
1602 + conf.check_cfg(package='glusterfs-api', args='"glusterfs-api >= 4" --cflags --libs',
1603 + msg='Checking for glusterfs-api >= 4', uselib_store="GFAPI")
1604 + conf.CHECK_HEADERS('api/glfs.h', lib='gfapi')
1605 + conf.CHECK_LIB('gfapi', shlib=True)
1606 +
1607 + if conf.CONFIG_SET('HAVE_API_GLFS_H'):
1608 + conf.DEFINE('HAVE_GLUSTERFS', '1')
1609 + else:
1610 + conf.SET_TARGET_TYPE('gfapi', 'EMPTY')
1611 + conf.undefine('HAVE_GLUSTERFS')
1612 + else:
1613 + conf.SET_TARGET_TYPE('gfapi', 'EMPTY')
1614 + conf.undefine('HAVE_GLUSTERFS')
1615 +
1616
1617 conf.CHECK_CODE('__attribute__((destructor)) static void cleanup(void) { }',
1618 'HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR',
1619 @@ -1794,6 +1813,9 @@ main() {
1620 if conf.CONFIG_SET('HAVE_GPFS'):
1621 default_shared_modules.extend(TO_LIST('vfs_gpfs vfs_gpfs_hsm_notify'))
1622
1623 + if conf.CONFIG_SET('HAVE_GLUSTERFS'):
1624 + default_shared_modules.extend(TO_LIST('vfs_glusterfs'))
1625 +
1626 explicit_shared_modules = TO_LIST(Options.options.shared_modules, delimiter=',')
1627 explicit_static_modules = TO_LIST(Options.options.static_modules, delimiter=',')
1628
1629 --
1630 1.9.3
1631
1632
1633 From e2b70ae1e9b072173de2b7d6140381b910d436b4 Mon Sep 17 00:00:00 2001
1634 From: Raghavendra Talur <rtalur@redhat.com>
1635 Date: Thu, 20 Jun 2013 17:58:15 -0700
1636 Subject: [PATCH 2/9] PATCHSET13: vfs_glusterfs: New file creation fix.
1637
1638 When a new document is created in explorer, a check for file_exist is made.
1639 vfs_gluster_get_real_filename was returning 0 even when the file did not
1640 exist.
1641 ---
1642 source3/modules/vfs_glusterfs.c | 6 ++++--
1643 1 file changed, 4 insertions(+), 2 deletions(-)
1644
1645 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
1646 index 4beac1d..3752940 100644
1647 --- a/source3/modules/vfs_glusterfs.c
1648 +++ b/source3/modules/vfs_glusterfs.c
1649 @@ -839,8 +839,10 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle,
1650 "user.glusterfs.get_real_filename:%s", name);
1651
1652 ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1);
1653 - if (ret == -1 && errno == ENODATA) {
1654 - errno = EOPNOTSUPP;
1655 + if (ret == -1) {
1656 + if (errno == ENODATA) {
1657 + errno = EOPNOTSUPP;
1658 + }
1659 return -1;
1660 }
1661
1662 --
1663 1.9.3
1664
1665
1666 From e963ec42b17cdc7369e4b79387447bb3ddc99d2a Mon Sep 17 00:00:00 2001
1667 From: susant <spalai@redhat.com>
1668 Date: Wed, 7 Aug 2013 01:00:31 -0500
1669 Subject: [PATCH 3/9] PATCHSET13: vfs_glusterfs: Volume capacity reported to
1670 Windows is incorrect
1671
1672 VFS plugin was sending the actual size of the volume instead of the
1673 total number of block units because of which windows was getting the
1674 wrong volume capacity.
1675
1676 Signed-off-by: susant <spalai@redhat.com>
1677 Reviewed-by: Anand Avati <avati@redhat.com>
1678 ---
1679 source3/modules/vfs_glusterfs.c | 11 ++++-------
1680 1 file changed, 4 insertions(+), 7 deletions(-)
1681
1682 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
1683 index 3752940..1502776 100644
1684 --- a/source3/modules/vfs_glusterfs.c
1685 +++ b/source3/modules/vfs_glusterfs.c
1686 @@ -297,7 +297,6 @@ vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
1687 uint64_t *dsize_p)
1688 {
1689 struct statvfs statvfs = { 0, };
1690 - uint64_t dfree = 0;
1691 int ret;
1692
1693 ret = glfs_statvfs(handle->data, path, &statvfs);
1694 @@ -307,19 +306,17 @@ vfs_gluster_disk_free(struct vfs_handle_struct *handle, const char *path,
1695 return -1;
1696 }
1697
1698 - dfree = statvfs.f_bsize * statvfs.f_bavail;
1699 -
1700 if (bsize_p) {
1701 - *bsize_p = statvfs.f_bsize;
1702 + *bsize_p = (uint64_t)statvfs.f_bsize; /* Block size */
1703 }
1704 if (dfree_p) {
1705 - *dfree_p = dfree;
1706 + *dfree_p = (uint64_t)statvfs.f_bavail; /* Available Block units */
1707 }
1708 if (dsize_p) {
1709 - *dsize_p = statvfs.f_bsize * statvfs.f_blocks;
1710 + *dsize_p = (uint64_t)statvfs.f_blocks; /* Total Block units */
1711 }
1712
1713 - return dfree;
1714 + return (uint64_t)statvfs.f_bavail;
1715 }
1716
1717 static int
1718 --
1719 1.9.3
1720
1721
1722 From 1d41227866ede7ae14857105abd6b322e8e41525 Mon Sep 17 00:00:00 2001
1723 From: Anand Avati <avati@redhat.com>
1724 Date: Mon, 12 Aug 2013 14:59:24 -0500
1725 Subject: [PATCH 4/9] PATCHSET13: vfs_glusterfs: Implement proper
1726 mashalling/unmarshalling of ACLs
1727
1728 Use the primitives available in Samba byteorder.h for implementing
1729 proper (un)marshalling of ACL xattrs.
1730
1731 Signed-off-by: Anand Avati <avati@redhat.com>
1732 Reviewed-by: Raghavendra Talur <rtalur@redhat.com>
1733 Reviewed-by: Jeremy Allison <jra@samba.org>
1734 Tested-by: "Jose A. Rivera" <jarrpa@redhat.com>
1735 ---
1736 source3/modules/vfs_glusterfs.c | 154 +++++++++++++++++++++++++++++-----------
1737 1 file changed, 112 insertions(+), 42 deletions(-)
1738
1739 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
1740 index 1502776..1b81d06 100644
1741 --- a/source3/modules/vfs_glusterfs.c
1742 +++ b/source3/modules/vfs_glusterfs.c
1743 @@ -963,13 +963,36 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
1744 return -1;
1745 }
1746
1747 -/* Posix ACL Operations */
1748 +/*
1749 + Gluster ACL Format:
1750 +
1751 + Size = 4 (header) + N * 8 (entry)
1752 +
1753 + Offset Size Field (Little Endian)
1754 + -------------------------------------
1755 + 0-3 4-byte Version
1756 +
1757 + 4-5 2-byte Entry-1 tag
1758 + 6-7 2-byte Entry-1 perm
1759 + 8-11 4-byte Entry-1 id
1760 +
1761 + 12-13 2-byte Entry-2 tag
1762 + 14-15 2-byte Entry-2 perm
1763 + 16-19 4-byte Entry-2 id
1764
1765 + ...
1766 +
1767 + */
1768 +
1769 +/* header version */
1770 #define GLUSTER_ACL_VERSION 2
1771 +
1772 +/* perm bits */
1773 #define GLUSTER_ACL_READ 0x04
1774 #define GLUSTER_ACL_WRITE 0x02
1775 #define GLUSTER_ACL_EXECUTE 0x01
1776
1777 +/* tag values */
1778 #define GLUSTER_ACL_UNDEFINED_TAG 0x00
1779 #define GLUSTER_ACL_USER_OBJ 0x01
1780 #define GLUSTER_ACL_USER 0x02
1781 @@ -980,57 +1003,48 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
1782
1783 #define GLUSTER_ACL_UNDEFINED_ID (-1)
1784
1785 -struct gluster_ace {
1786 - uint16_t tag;
1787 - uint16_t perm;
1788 - uint32_t id;
1789 -};
1790 -
1791 -struct gluster_acl_header {
1792 - uint32_t version;
1793 - struct gluster_ace entries[];
1794 -};
1795 +#define GLUSTER_ACL_HEADER_SIZE 4
1796 +#define GLUSTER_ACL_ENTRY_SIZE 8
1797
1798 static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1799 {
1800 int count;
1801 size_t size;
1802 - struct gluster_ace *ace;
1803 struct smb_acl_entry *smb_ace;
1804 - struct gluster_acl_header *hdr;
1805 struct smb_acl_t *result;
1806 int i;
1807 + int offset;
1808 uint16_t tag;
1809 uint16_t perm;
1810 uint32_t id;
1811
1812 size = xattr_size;
1813
1814 - if (size < sizeof(*hdr)) {
1815 - /* ACL should be at least as big as the header */
1816 + if (size < GLUSTER_ACL_HEADER_SIZE) {
1817 + /* ACL should be at least as big as the header (4 bytes) */
1818 errno = EINVAL;
1819 return NULL;
1820 }
1821
1822 - size -= sizeof(*hdr);
1823 + size -= GLUSTER_ACL_HEADER_SIZE; /* size of header = 4 bytes */
1824
1825 - if (size % sizeof(*ace)) {
1826 + if (size % GLUSTER_ACL_ENTRY_SIZE) {
1827 /* Size of entries must strictly be a multiple of
1828 - size of an ACE
1829 + size of an ACE (8 bytes)
1830 */
1831 errno = EINVAL;
1832 return NULL;
1833 }
1834
1835 - count = size / sizeof(*ace);
1836 -
1837 - hdr = (void *)buf;
1838 + count = size / GLUSTER_ACL_ENTRY_SIZE;
1839
1840 - if (ntohl(hdr->version) != GLUSTER_ACL_VERSION) {
1841 + /* Version is the first 4 bytes of the ACL */
1842 + if (IVAL(buf, 0) != GLUSTER_ACL_VERSION) {
1843 DEBUG(0, ("Unknown gluster ACL version: %d\n",
1844 - ntohl(hdr->version)));
1845 + IVAL(buf, 0)));
1846 return NULL;
1847 }
1848 + offset = GLUSTER_ACL_HEADER_SIZE;
1849
1850 result = SMB_MALLOC(sizeof(struct smb_acl_t) + (sizeof(struct smb_acl_entry) * count));
1851 if (!result) {
1852 @@ -1041,10 +1055,19 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1853 result->count = count;
1854
1855 smb_ace = result->acl;
1856 - ace = hdr->entries;
1857
1858 for (i = 0; i < count; i++) {
1859 - tag = ntohs(ace->tag);
1860 + /* TAG is the first 2 bytes of an entry */
1861 + tag = SVAL(buf, offset);
1862 + offset += 2;
1863 +
1864 + /* PERM is the next 2 bytes of an entry */
1865 + perm = SVAL(buf, offset);
1866 + offset += 2;
1867 +
1868 + /* ID is the last 4 bytes of an entry */
1869 + id = IVAL(buf, offset);
1870 + offset += 4;
1871
1872 switch(tag) {
1873 case GLUSTER_ACL_USER:
1874 @@ -1070,7 +1093,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1875 return NULL;
1876 }
1877
1878 - id = ntohl(ace->id);
1879
1880 switch(smb_ace->a_type) {
1881 case SMB_ACL_USER:
1882 @@ -1083,8 +1105,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1883 break;
1884 }
1885
1886 - perm = ntohs(ace->perm);
1887 -
1888 smb_ace->a_perm = 0;
1889 smb_ace->a_perm |=
1890 ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0);
1891 @@ -1093,28 +1113,61 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size)
1892 smb_ace->a_perm |=
1893 ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
1894
1895 - ace++;
1896 smb_ace++;
1897 }
1898
1899 return result;
1900 }
1901
1902 +
1903 +static int gluster_ace_cmp(const void *left, const void *right)
1904 +{
1905 + int ret = 0;
1906 + uint16_t tag_left, tag_right;
1907 + uint32_t id_left, id_right;
1908 +
1909 + /*
1910 + Sorting precedence:
1911 +
1912 + - Smaller TAG values must be earlier.
1913 +
1914 + - Within same TAG, smaller identifiers must be earlier, E.g:
1915 + UID 0 entry must be earlier than UID 200
1916 + GID 17 entry must be earlier than GID 19
1917 + */
1918 +
1919 + /* TAG is the first element in the entry */
1920 + tag_left = SVAL(left, 0);
1921 + tag_right = SVAL(right, 0);
1922 +
1923 + ret = (tag_left - tag_right);
1924 + if (!ret) {
1925 + /* ID is the third element in the entry, after two short
1926 + integers (tag and perm), i.e at offset 4.
1927 + */
1928 + id_left = IVAL(left, 4);
1929 + id_right = IVAL(right, 4);
1930 + ret = id_left - id_right;
1931 + }
1932 +
1933 + return ret;
1934 +}
1935 +
1936 +
1937 static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
1938 {
1939 ssize_t size;
1940 - struct gluster_ace *ace;
1941 struct smb_acl_entry *smb_ace;
1942 - struct gluster_acl_header *hdr;
1943 int i;
1944 int count;
1945 uint16_t tag;
1946 uint16_t perm;
1947 uint32_t id;
1948 + int offset;
1949
1950 count = theacl->count;
1951
1952 - size = sizeof(*hdr) + (count * sizeof(*ace));
1953 + size = GLUSTER_ACL_HEADER_SIZE + (count * GLUSTER_ACL_ENTRY_SIZE);
1954 if (!buf) {
1955 return size;
1956 }
1957 @@ -1124,13 +1177,14 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
1958 return -1;
1959 }
1960
1961 - hdr = (void *)buf;
1962 - ace = hdr->entries;
1963 smb_ace = theacl->acl;
1964
1965 - hdr->version = htonl(GLUSTER_ACL_VERSION);
1966 + /* Version is the first 4 bytes of the ACL */
1967 + SIVAL(buf, 0, GLUSTER_ACL_VERSION);
1968 + offset = GLUSTER_ACL_HEADER_SIZE;
1969
1970 for (i = 0; i < count; i++) {
1971 + /* Calculate tag */
1972 switch(smb_ace->a_type) {
1973 case SMB_ACL_USER:
1974 tag = GLUSTER_ACL_USER;
1975 @@ -1157,8 +1211,8 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
1976 return -1;
1977 }
1978
1979 - ace->tag = ntohs(tag);
1980
1981 + /* Calculate id */
1982 switch(smb_ace->a_type) {
1983 case SMB_ACL_USER:
1984 id = smb_ace->uid;
1985 @@ -1171,20 +1225,36 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
1986 break;
1987 }
1988
1989 - ace->id = ntohl(id);
1990 + /* Calculate perm */
1991 + perm = 0;
1992
1993 - ace->perm = 0;
1994 - ace->perm |=
1995 + perm |=
1996 ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
1997 - ace->perm |=
1998 + perm |=
1999 ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
2000 - ace->perm |=
2001 + perm |=
2002 ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
2003
2004 - ace++;
2005 +
2006 + /* TAG is the first 2 bytes of an entry */
2007 + SSVAL(buf, offset, tag);
2008 + offset += 2;
2009 +
2010 + /* PERM is the next 2 bytes of an entry */
2011 + SSVAL(buf, offset, perm);
2012 + offset += 2;
2013 +
2014 + /* ID is the last 4 bytes of an entry */
2015 + SIVAL(buf, offset, id);
2016 + offset += 4;
2017 +
2018 smb_ace++;
2019 }
2020
2021 + /* Skip the header, sort @count number of 8-byte entries */
2022 + qsort(buf+GLUSTER_ACL_HEADER_SIZE, count, GLUSTER_ACL_ENTRY_SIZE,
2023 + gluster_ace_cmp);
2024 +
2025 return size;
2026 }
2027
2028 --
2029 1.9.3
2030
2031
2032 From 26673935299da8ce830ff9d0ea5df18f52092092 Mon Sep 17 00:00:00 2001
2033 From: "Christopher R. Hertel" <crh@redhat.com>
2034 Date: Thu, 29 Aug 2013 11:01:24 -0500
2035 Subject: [PATCH 5/9] PATCHSET13: vfs_glusterfs: Fix excessive debug output
2036 from vfs_gluster_open().
2037
2038 The vfs_gluster_open() function generates a debug message (at level 0)
2039 for every failed attempt to open a pathname. This includes cases in
2040 which attempts are made to open a directory as a file (those attempts
2041 are retried calling vfs_gluster_opendir()). The result is that the log
2042 file fills with messages about failed attempts to open directories,
2043 because they are directories. This patch ensures that failed attempts
2044 to open directories as files are logged at log level 4, not 0. In
2045 addition, other failed open attempts are logged at level 1, not 0.
2046
2047 Signed-off-by: Christopher R. Hertel <crh@redhat.com>
2048 Reviewed-by : Susant Palai <spalai@redhat.com>
2049 Reviewed-by : Raghavendra Talur <rtalur@redhat.com>
2050 Reviewed-by : Jose A. Rivera <jarrpa@redhat.com>
2051 ---
2052 source3/modules/vfs_glusterfs.c | 3 ---
2053 1 file changed, 3 deletions(-)
2054
2055 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
2056 index 1b81d06..b92c7fd 100644
2057 --- a/source3/modules/vfs_glusterfs.c
2058 +++ b/source3/modules/vfs_glusterfs.c
2059 @@ -488,11 +488,8 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle,
2060 }
2061
2062 if (glfd == NULL) {
2063 - DEBUG(0, ("glfs_{open[dir],creat}(%s) failed: %s\n",
2064 - smb_fname->base_name, strerror(errno)));
2065 return -1;
2066 }
2067 -
2068 return glfd_fd_store(glfd);
2069 }
2070
2071 --
2072 1.9.3
2073
2074
2075 From f396be725dd8e8f93b0eed1b23fcf0a0f61303a9 Mon Sep 17 00:00:00 2001
2076 From: Andreas Schneider <asn@samba.org>
2077 Date: Mon, 4 Nov 2013 12:32:05 +0100
2078 Subject: [PATCH 6/9] PATCHSET13: vfs: Fix some build warnings in glusterfs.
2079
2080 Signed-off-by: Andreas Schneider <asn@samba.org>
2081 Reviewed-by: David Disseldorp <ddiss@samba.org>
2082 ---
2083 source3/modules/vfs_glusterfs.c | 4 ++--
2084 1 file changed, 2 insertions(+), 2 deletions(-)
2085
2086 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
2087 index b92c7fd..4b8da4a 100644
2088 --- a/source3/modules/vfs_glusterfs.c
2089 +++ b/source3/modules/vfs_glusterfs.c
2090 @@ -1262,7 +1262,7 @@ static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle,
2091 {
2092 struct smb_acl_t *result;
2093 char *buf;
2094 - char *key;
2095 + const char *key;
2096 ssize_t ret;
2097
2098 switch (type) {
2099 @@ -1324,7 +1324,7 @@ static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle,
2100 SMB_ACL_T theacl)
2101 {
2102 int ret;
2103 - char *key;
2104 + const char *key;
2105 char *buf;
2106 ssize_t size;
2107
2108 --
2109 1.9.3
2110
2111
2112 From 2b136f8999e171d15736d0a532353799b7251ae2 Mon Sep 17 00:00:00 2001
2113 From: Andreas Schneider <asn@samba.org>
2114 Date: Fri, 15 Nov 2013 17:02:19 +0100
2115 Subject: [PATCH 7/9] PATCHSET13: s3-vfs: Make glfs_set_preopened() static.
2116
2117 Signed-off-by: Andreas Schneider <asn@samba.org>
2118 Reviewed-by: Jeremy Allison <jra@samba.org>
2119 ---
2120 source3/modules/vfs_glusterfs.c | 2 +-
2121 1 file changed, 1 insertion(+), 1 deletion(-)
2122
2123 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
2124 index 4b8da4a..ef505a3 100644
2125 --- a/source3/modules/vfs_glusterfs.c
2126 +++ b/source3/modules/vfs_glusterfs.c
2127 @@ -141,7 +141,7 @@ static struct glfs_preopened {
2128 } *glfs_preopened;
2129
2130
2131 -int glfs_set_preopened(const char *volume, glfs_t *fs)
2132 +static int glfs_set_preopened(const char *volume, glfs_t *fs)
2133 {
2134 struct glfs_preopened *entry = NULL;
2135
2136 --
2137 1.9.3
2138
2139
2140 From 9b2c8854a5a27e4fdbe5191abf174d3152b0edfd Mon Sep 17 00:00:00 2001
2141 From: Poornima Gurusiddaiah <pgurusid@redhat.com>
2142 Date: Sun, 24 Nov 2013 21:37:53 +0000
2143 Subject: [PATCH 8/9] PATCHSET13: vfs_glusterfs: Enable per client log file
2144
2145 In Samba configuration file, one of the options of gluster type is
2146 log file, the value of this option was not allowed to contain any
2147 variables, as a result all the clients would have a single log file,
2148 which complicated debugging.
2149 In this patch, variable substitution is performed for gluster log file.
2150 Hence allowing user to customise the gluster log file name.
2151
2152 Signed-off-by: Poornima Gurusiddaiah <pgurusid@redhat.com>
2153 Reviewed-by: Ira Cooper <ira@samba.org>
2154 ---
2155 source3/modules/vfs_glusterfs.c | 41 ++++++++++++++++++++++-------------------
2156 1 file changed, 22 insertions(+), 19 deletions(-)
2157
2158 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
2159 index ef505a3..3757968 100644
2160 --- a/source3/modules/vfs_glusterfs.c
2161 +++ b/source3/modules/vfs_glusterfs.c
2162 @@ -205,12 +205,12 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle,
2163 {
2164 const char *volfile_server;
2165 const char *volume;
2166 - const char *logfile;
2167 + char *logfile;
2168 int loglevel;
2169 glfs_t *fs;
2170 - int ret;
2171 + int ret = 0;
2172
2173 - logfile = lp_parm_const_string(SNUM(handle->conn), "glusterfs",
2174 + logfile = lp_parm_talloc_string(SNUM(handle->conn), "glusterfs",
2175 "logfile", NULL);
2176
2177 loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1);
2178 @@ -229,57 +229,60 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle,
2179
2180 fs = glfs_find_preopened(volume);
2181 if (fs) {
2182 - goto found;
2183 + goto done;
2184 }
2185
2186 fs = glfs_new(volume);
2187 if (fs == NULL) {
2188 - return -1;
2189 + ret = -1;
2190 + goto done;
2191 }
2192
2193 ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 0);
2194 if (ret < 0) {
2195 DEBUG(0, ("Failed to set volfile_server %s\n", volfile_server));
2196 - glfs_fini(fs);
2197 - return -1;
2198 + goto done;
2199 }
2200
2201 ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl",
2202 "true");
2203 if (ret < 0) {
2204 DEBUG(0, ("%s: Failed to set xlator options\n", volume));
2205 - glfs_fini(fs);
2206 - return -1;
2207 + goto done;
2208 }
2209
2210 ret = glfs_set_logging(fs, logfile, loglevel);
2211 if (ret < 0) {
2212 DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n",
2213 volume, logfile, loglevel));
2214 - glfs_fini(fs);
2215 - return -1;
2216 + goto done;
2217 }
2218
2219 ret = glfs_init(fs);
2220 if (ret < 0) {
2221 DEBUG(0, ("%s: Failed to initialize volume (%s)\n",
2222 volume, strerror(errno)));
2223 - glfs_fini(fs);
2224 - return -1;
2225 + goto done;
2226 }
2227
2228 ret = glfs_set_preopened(volume, fs);
2229 if (ret < 0) {
2230 DEBUG(0, ("%s: Failed to register volume (%s)\n",
2231 volume, strerror(errno)));
2232 - glfs_fini(fs);
2233 + goto done;
2234 + }
2235 +done:
2236 + talloc_free(logfile);
2237 + if (ret < 0) {
2238 + if (fs)
2239 + glfs_fini(fs);
2240 return -1;
2241 + } else {
2242 + DEBUG(0, ("%s: Initialized volume from server %s\n",
2243 + volume, volfile_server));
2244 + handle->data = fs;
2245 + return 0;
2246 }
2247 -found:
2248 - DEBUG(0, ("%s: Initialized volume from server %s\n",
2249 - volume, volfile_server));
2250 - handle->data = fs;
2251 - return 0;
2252 }
2253
2254 static void vfs_gluster_disconnect(struct vfs_handle_struct *handle)
2255 --
2256 1.9.3
2257
2258
2259 From 8577c573dcd44e26579a6594b83a6d582faef14c Mon Sep 17 00:00:00 2001
2260 From: Niels de Vos <ndevos@redhat.com>
2261 Date: Fri, 10 Jan 2014 16:26:18 +0100
2262 Subject: [PATCH 9/9] PATCHSET13: vfs/glusterfs: in case atime is not passed,
2263 set it to the current atime
2264
2265 The Linux CIFS client does not pass an updated atime when a write() is
2266 done. This causes the vfs/glusterfs module to set the atime to -1 on the
2267 Gluster backend, resulting in an atime far in the future (year 2106).
2268
2269 Signed-off-by: Niels de Vos <ndevos@redhat.com>
2270 Reviewed-by: Ira Cooper <ira@samba.org>
2271 Reviewed-by: Jeremy Allison <jra@samba.org>
2272
2273 Autobuild-User(master): Jeremy Allison <jra@samba.org>
2274 Autobuild-Date(master): Wed Jan 15 21:31:30 CET 2014 on sn-devel-104
2275 ---
2276 source3/modules/vfs_glusterfs.c | 26 ++++++++++++++++++++++----
2277 1 file changed, 22 insertions(+), 4 deletions(-)
2278
2279 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
2280 index 3757968..24f80dd 100644
2281 --- a/source3/modules/vfs_glusterfs.c
2282 +++ b/source3/modules/vfs_glusterfs.c
2283 @@ -675,10 +675,28 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
2284 {
2285 struct timespec times[2];
2286
2287 - times[0].tv_sec = ft->atime.tv_sec;
2288 - times[0].tv_nsec = ft->atime.tv_nsec;
2289 - times[1].tv_sec = ft->mtime.tv_sec;
2290 - times[1].tv_nsec = ft->mtime.tv_nsec;
2291 + if (null_timespec(ft->atime)) {
2292 + times[0].tv_sec = smb_fname->st.st_ex_atime.tv_sec;
2293 + times[0].tv_nsec = smb_fname->st.st_ex_atime.tv_nsec;
2294 + } else {
2295 + times[0].tv_sec = ft->atime.tv_sec;
2296 + times[0].tv_nsec = ft->atime.tv_nsec;
2297 + }
2298 +
2299 + if (null_timespec(ft->mtime)) {
2300 + times[1].tv_sec = smb_fname->st.st_ex_mtime.tv_sec;
2301 + times[1].tv_nsec = smb_fname->st.st_ex_mtime.tv_nsec;
2302 + } else {
2303 + times[1].tv_sec = ft->mtime.tv_sec;
2304 + times[1].tv_nsec = ft->mtime.tv_nsec;
2305 + }
2306 +
2307 + if ((timespec_compare(&times[0],
2308 + &smb_fname->st.st_ex_atime) == 0) &&
2309 + (timespec_compare(&times[1],
2310 + &smb_fname->st.st_ex_mtime) == 0)) {
2311 + return 0;
2312 + }
2313
2314 return glfs_utimens(handle->data, smb_fname->base_name, times);
2315 }
2316 --
2317 1.9.3
2318