X-Git-Url: http://git.samba.org/samba.git/?p=gd%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source3%2Fmodules%2Fvfs_glusterfs.c;h=cffab7b986eea17a843540c5c359fd397a229ac1;hp=e5c691e1d9378bd8fb1b1e42f634879a5c8ffa0c;hb=9e1f792b2687f7e5514007405ef2987af35349cf;hpb=d35d6a2dfa92512049e762d7abc319c67118e705 diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index e5c691e1d93..cffab7b986e 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -19,90 +19,42 @@ along with this program. If not, see . */ +/** + * @file vfs_glusterfs.c + * @author Anand Avati + * @date May 2013 + * @brief Samba VFS module for glusterfs + * + * @todo + * - sendfile/recvfile support + * + * A Samba VFS module for GlusterFS, based on Gluster's libgfapi. + * This is a "bottom" vfs module (not something to be stacked on top of + * another module), and translates (most) calls to the closest actions + * available in libgfapi. + * + */ + #include "includes.h" #include "smbd/smbd.h" #include -#include "api/glfs.h" +#include #include "lib/util/dlinklist.h" +#include "lib/util/tevent_unix.h" +#include "smbd/globals.h" +#include "lib/util/sys_rw.h" +#include "smbprofile.h" +#include "modules/posixacl_xattr.h" #define DEFAULT_VOLFILE_SERVER "localhost" -/* - TODO - ---- - Short term: - - AIO support - - sendfile/recvfile support -*/ - -/* Helpers to provide 'integer' fds */ - -/* This is global. gfapi's FD operations do not - require filesystem context. -*/ - -static glfs_fd_t **glfd_fd; -static int glfd_fd_size; -static int glfd_fd_used; - -static int glfd_fd_store(glfs_fd_t *glfd) -{ - int i; - void *tmp; - - if (glfd_fd_size == glfd_fd_used) { - if (glfd_fd_size >= INT_MAX - 1) { - errno = ENOMEM; - return -1; - } - - tmp = talloc_realloc(glfd_fd, glfd_fd, glfs_fd_t *, - glfd_fd_size + 1); - if (tmp == NULL) { - errno = ENOMEM; - return -1; - } - - glfd_fd = tmp; - glfd_fd[glfd_fd_size] = 0; - glfd_fd_size++; - } - - for (i = 0; i < glfd_fd_size; i++) { - if (glfd_fd[i] == NULL) { - break; - } - } - glfd_fd_used++; - glfd_fd[i] = glfd; - return i; -} - -static glfs_fd_t *glfd_fd_get(int i) -{ - if (i < 0 || i >= glfd_fd_size) { - return NULL; - } - return glfd_fd[i]; -} - -static glfs_fd_t *glfd_fd_clear(int i) -{ - glfs_fd_t *glfd = NULL; - - if (i < 0 || i >= glfd_fd_size) { - return NULL; - } - - glfd = glfd_fd[i]; - - glfd_fd[i] = 0; - glfd_fd_used--; - return glfd; -} - -/* Helper to convert stat to stat_ex */ +static int read_fd = -1; +static int write_fd = -1; +static struct tevent_fd *aio_read_event = NULL; +/** + * Helper to convert struct stat to struct stat_ex. + */ static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src) { ZERO_STRUCTP(dst); @@ -116,36 +68,31 @@ static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src) dst->st_ex_rdev = src->st_rdev; dst->st_ex_size = src->st_size; dst->st_ex_atime.tv_sec = src->st_atime; -#ifdef STAT_HAVE_NSEC - dst->st_ex_atime.tv_nsec = src->st_atime_nsec; -#endif dst->st_ex_mtime.tv_sec = src->st_mtime; -#ifdef STAT_HAVE_NSEC - dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec; -#endif dst->st_ex_ctime.tv_sec = src->st_ctime; -#ifdef STAT_HAVE_NSEC - dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec; -#endif dst->st_ex_btime.tv_sec = src->st_mtime; + dst->st_ex_blksize = src->st_blksize; + dst->st_ex_blocks = src->st_blocks; #ifdef STAT_HAVE_NSEC + dst->st_ex_atime.tv_nsec = src->st_atime_nsec; + dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec; + dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec; dst->st_ex_btime.tv_nsec = src->st_mtime_nsec; #endif - dst->st_ex_blksize = src->st_blksize; - dst->st_ex_blocks = src->st_blocks; } /* pre-opened glfs_t */ static struct glfs_preopened { char *volume; + char *connectpath; glfs_t *fs; int ref; struct glfs_preopened *next, *prev; } *glfs_preopened; -int glfs_set_preopened(const char *volume, glfs_t *fs) +static int glfs_set_preopened(const char *volume, const char *connectpath, glfs_t *fs) { struct glfs_preopened *entry = NULL; @@ -162,6 +109,13 @@ int glfs_set_preopened(const char *volume, glfs_t *fs) return -1; } + entry->connectpath = talloc_strdup(entry, connectpath); + if (entry->connectpath == NULL) { + talloc_free(entry); + errno = ENOMEM; + return -1; + } + entry->fs = fs; entry->ref = 1; @@ -170,12 +124,14 @@ int glfs_set_preopened(const char *volume, glfs_t *fs) return 0; } -static glfs_t *glfs_find_preopened(const char *volume) +static glfs_t *glfs_find_preopened(const char *volume, const char *connectpath) { struct glfs_preopened *entry = NULL; for (entry = glfs_preopened; entry; entry = entry->next) { - if (strcmp(entry->volume, volume) == 0) { + if (strcmp(entry->volume, volume) == 0 && + strcmp(entry->connectpath, connectpath) == 0) + { entry->ref++; return entry->fs; } @@ -201,28 +157,138 @@ static void glfs_clear_preopened(glfs_t *fs) } } +static int vfs_gluster_set_volfile_servers(glfs_t *fs, + const char *volfile_servers) +{ + char *server = NULL; + int server_count = 0; + int server_success = 0; + int ret = -1; + TALLOC_CTX *frame = talloc_stackframe(); + + DBG_INFO("servers list %s\n", volfile_servers); + + while (next_token_talloc(frame, &volfile_servers, &server, " \t")) { + char *transport = NULL; + char *host = NULL; + int port = 0; + + server_count++; + DBG_INFO("server %d %s\n", server_count, server); + + /* Determine the transport type */ + if (strncmp(server, "unix+", 5) == 0) { + port = 0; + transport = talloc_strdup(frame, "unix"); + if (!transport) { + errno = ENOMEM; + goto out; + } + host = talloc_strdup(frame, server + 5); + if (!host) { + errno = ENOMEM; + goto out; + } + } else { + char *p = NULL; + char *port_index = NULL; + + if (strncmp(server, "tcp+", 4) == 0) { + server += 4; + } + + /* IPv6 is enclosed in [] + * ':' before ']' is part of IPv6 + * ':' after ']' indicates port + */ + p = server; + if (server[0] == '[') { + server++; + p = index(server, ']'); + if (p == NULL) { + /* Malformed IPv6 */ + continue; + } + p[0] = '\0'; + p++; + } + + port_index = index(p, ':'); + + if (port_index == NULL) { + port = 0; + } else { + port = atoi(port_index + 1); + port_index[0] = '\0'; + } + transport = talloc_strdup(frame, "tcp"); + if (!transport) { + errno = ENOMEM; + goto out; + } + host = talloc_strdup(frame, server); + if (!host) { + errno = ENOMEM; + goto out; + } + } + + DBG_INFO("Calling set volfile server with params " + "transport=%s, host=%s, port=%d\n", transport, + host, port); + + ret = glfs_set_volfile_server(fs, transport, host, port); + if (ret < 0) { + DBG_WARNING("Failed to set volfile_server " + "transport=%s, host=%s, port=%d (%s)\n", + transport, host, port, strerror(errno)); + } else { + server_success++; + } + } + +out: + if (server_count == 0) { + ret = -1; + } else if (server_success < server_count) { + DBG_WARNING("Failed to set %d out of %d servers parsed\n", + server_count - server_success, server_count); + ret = 0; + } + + TALLOC_FREE(frame); + return ret; +} + /* Disk Operations */ static int vfs_gluster_connect(struct vfs_handle_struct *handle, const char *service, const char *user) { - const char *volfile_server; + const char *volfile_servers; const char *volume; - const char *logfile; + char *logfile; int loglevel; - glfs_t *fs; - int ret; + glfs_t *fs = NULL; + TALLOC_CTX *tmp_ctx; + int ret = 0; - logfile = lp_parm_const_string(SNUM(handle->conn), "glusterfs", + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = -1; + goto done; + } + logfile = lp_parm_talloc_string(tmp_ctx, SNUM(handle->conn), "glusterfs", "logfile", NULL); loglevel = lp_parm_int(SNUM(handle->conn), "glusterfs", "loglevel", -1); - volfile_server = lp_parm_const_string(SNUM(handle->conn), "glusterfs", - "volfile_server", NULL); - if (volfile_server == NULL) { - volfile_server = DEFAULT_VOLFILE_SERVER; + volfile_servers = lp_parm_talloc_string(tmp_ctx, SNUM(handle->conn), + "glusterfs", "volfile_server", + NULL); + if (volfile_servers == NULL) { + volfile_servers = DEFAULT_VOLFILE_SERVER; } volume = lp_parm_const_string(SNUM(handle->conn), "glusterfs", "volume", @@ -231,59 +297,82 @@ static int vfs_gluster_connect(struct vfs_handle_struct *handle, volume = service; } - fs = glfs_find_preopened(volume); + fs = glfs_find_preopened(volume, handle->conn->connectpath); if (fs) { - goto found; + goto done; } fs = glfs_new(volume); if (fs == NULL) { - return -1; + ret = -1; + goto done; } - ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 0); + ret = vfs_gluster_set_volfile_servers(fs, volfile_servers); if (ret < 0) { - DEBUG(0, ("Failed to set volfile_server %s\n", volfile_server)); - glfs_fini(fs); - return -1; + DBG_ERR("Failed to set volfile_servers from list %s\n", + volfile_servers); + goto done; } ret = glfs_set_xlator_option(fs, "*-md-cache", "cache-posix-acl", "true"); if (ret < 0) { DEBUG(0, ("%s: Failed to set xlator options\n", volume)); - glfs_fini(fs); - return -1; + goto done; + } + + + ret = glfs_set_xlator_option(fs, "*-snapview-client", + "snapdir-entry-path", + handle->conn->connectpath); + if (ret < 0) { + DEBUG(0, ("%s: Failed to set xlator option:" + " snapdir-entry-path\n", volume)); + goto done; } ret = glfs_set_logging(fs, logfile, loglevel); if (ret < 0) { DEBUG(0, ("%s: Failed to set logfile %s loglevel %d\n", volume, logfile, loglevel)); - glfs_fini(fs); - return -1; + goto done; } ret = glfs_init(fs); if (ret < 0) { DEBUG(0, ("%s: Failed to initialize volume (%s)\n", volume, strerror(errno))); - glfs_fini(fs); - return -1; + goto done; } - ret = glfs_set_preopened(volume, fs); + ret = glfs_set_preopened(volume, handle->conn->connectpath, fs); if (ret < 0) { DEBUG(0, ("%s: Failed to register volume (%s)\n", volume, strerror(errno))); - glfs_fini(fs); - return -1; + goto done; } -found: - DEBUG(0, ("%s: Initialized volume from server %s\n", - volume, volfile_server)); - handle->data = fs; - return 0; + + /* + * The shadow_copy2 module will fail to export subdirectories + * of a gluster volume unless we specify the mount point, + * because the detection fails if the file system is not + * locally mounted: + * https://bugzilla.samba.org/show_bug.cgi?id=13091 + */ + lp_do_parameter(SNUM(handle->conn), "shadow:mountpoint", "/"); + +done: + if (ret < 0) { + if (fs) + glfs_fini(fs); + } else { + DBG_ERR("%s: Initialized volume from servers %s\n", + volume, volfile_servers); + handle->data = fs; + } + talloc_free(tmp_ctx); + return ret; } static void vfs_gluster_disconnect(struct vfs_handle_struct *handle) @@ -296,14 +385,15 @@ static void vfs_gluster_disconnect(struct vfs_handle_struct *handle) } static uint64_t vfs_gluster_disk_free(struct vfs_handle_struct *handle, - const char *path, bool small_query, - uint64_t *bsize_p, uint64_t *dfree_p, - uint64_t *dsize_p) + const struct smb_filename *smb_fname, + uint64_t *bsize_p, + uint64_t *dfree_p, + uint64_t *dsize_p) { struct statvfs statvfs = { 0, }; int ret; - ret = glfs_statvfs(handle->data, path, &statvfs); + ret = glfs_statvfs(handle->data, smb_fname->base_name, &statvfs); if (ret < 0) { return -1; } @@ -322,8 +412,10 @@ static uint64_t vfs_gluster_disk_free(struct vfs_handle_struct *handle, } static int vfs_gluster_get_quota(struct vfs_handle_struct *handle, - enum SMB_QUOTA_TYPE qtype, unid_t id, - SMB_DISK_QUOTA *qt) + const struct smb_filename *smb_fname, + enum SMB_QUOTA_TYPE qtype, + unid_t id, + SMB_DISK_QUOTA *qt) { errno = ENOSYS; return -1; @@ -338,16 +430,16 @@ vfs_gluster_set_quota(struct vfs_handle_struct *handle, } static int vfs_gluster_statvfs(struct vfs_handle_struct *handle, - const char *path, - struct vfs_statvfs_struct *vfs_statvfs) + const struct smb_filename *smb_fname, + struct vfs_statvfs_struct *vfs_statvfs) { struct statvfs statvfs = { 0, }; int ret; - ret = glfs_statvfs(handle->data, path, &statvfs); + ret = glfs_statvfs(handle->data, smb_fname->base_name, &statvfs); if (ret < 0) { DEBUG(0, ("glfs_statvfs(%s) failed: %s\n", - path, strerror(errno))); + smb_fname->base_name, strerror(errno))); return -1; } @@ -380,15 +472,16 @@ static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle, } static DIR *vfs_gluster_opendir(struct vfs_handle_struct *handle, - const char *path, const char *mask, - uint32 attributes) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attributes) { glfs_fd_t *fd; - fd = glfs_opendir(handle->data, path); + fd = glfs_opendir(handle->data, smb_fname->base_name); if (fd == NULL) { DEBUG(0, ("glfs_opendir(%s) failed: %s\n", - path, strerror(errno))); + smb_fname->base_name, strerror(errno))); } return (DIR *) fd; @@ -396,9 +489,9 @@ static DIR *vfs_gluster_opendir(struct vfs_handle_struct *handle, static DIR *vfs_gluster_fdopendir(struct vfs_handle_struct *handle, files_struct *fsp, const char *mask, - uint32 attributes) + uint32_t attributes) { - return (DIR *) glfd_fd_get(fsp->fh->fd); + return (DIR *) *(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp); } static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp) @@ -448,21 +541,17 @@ static void vfs_gluster_rewinddir(struct vfs_handle_struct *handle, DIR *dirp) glfs_seekdir((void *)dirp, 0); } -static void vfs_gluster_init_search_op(struct vfs_handle_struct *handle, - DIR *dirp) -{ - return; -} - -static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, const char *path, +static int vfs_gluster_mkdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, mode_t mode) { - return glfs_mkdir(handle->data, path, mode); + return glfs_mkdir(handle->data, smb_fname->base_name, mode); } -static int vfs_gluster_rmdir(struct vfs_handle_struct *handle, const char *path) +static int vfs_gluster_rmdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - return glfs_rmdir(handle->data, path); + return glfs_rmdir(handle->data, smb_fname->base_name); } static int vfs_gluster_open(struct vfs_handle_struct *handle, @@ -470,6 +559,7 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle, int flags, mode_t mode) { glfs_fd_t *glfd; + glfs_fd_t **p_tmp; if (flags & O_DIRECTORY) { glfd = glfs_opendir(handle->data, smb_fname->base_name); @@ -483,55 +573,248 @@ static int vfs_gluster_open(struct vfs_handle_struct *handle, if (glfd == NULL) { return -1; } - return glfd_fd_store(glfd); + p_tmp = VFS_ADD_FSP_EXTENSION(handle, fsp, glfs_fd_t *, NULL); + *p_tmp = glfd; + /* An arbitrary value for error reporting, so you know its us. */ + return 13371337; } static int vfs_gluster_close(struct vfs_handle_struct *handle, files_struct *fsp) { - return glfs_close(glfd_fd_clear(fsp->fh->fd)); + glfs_fd_t *glfd; + glfd = *(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp); + VFS_REMOVE_FSP_EXTENSION(handle, fsp); + return glfs_close(glfd); } static ssize_t vfs_gluster_read(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n) { - return glfs_read(glfd_fd_get(fsp->fh->fd), data, n, 0); + return glfs_read(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), data, n, 0); } static ssize_t vfs_gluster_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n, off_t offset) { - return glfs_pread(glfd_fd_get(fsp->fh->fd), data, n, offset, 0); + return glfs_pread(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), data, n, offset, 0); } -static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct - *handle, TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - files_struct *fsp, void *data, - size_t n, off_t offset) +struct glusterfs_aio_state; + +struct glusterfs_aio_wrapper { + struct glusterfs_aio_state *state; +}; + +struct glusterfs_aio_state { + ssize_t ret; + struct tevent_req *req; + bool cancelled; + struct vfs_aio_state vfs_aio_state; + struct timespec start; +}; + +static int aio_wrapper_destructor(struct glusterfs_aio_wrapper *wrap) { - errno = ENOTSUP; - return NULL; + if (wrap->state != NULL) { + wrap->state->cancelled = true; + } + + return 0; } -static ssize_t vfs_gluster_pread_recv(struct tevent_req *req, int *err) +/* + * This function is the callback that will be called on glusterfs + * threads once the async IO submitted is complete. To notify + * Samba of the completion we use a pipe based queue. + */ +static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, void *data) { - errno = ENOTSUP; - return -1; + struct glusterfs_aio_state *state = NULL; + int sts = 0; + struct timespec end; + + state = (struct glusterfs_aio_state *)data; + + PROFILE_TIMESTAMP(&end); + + if (ret < 0) { + state->ret = -1; + state->vfs_aio_state.error = errno; + } else { + state->ret = ret; + } + state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start); + + /* + * Write the state pointer to glusterfs_aio_state to the + * pipe, so we can call tevent_req_done() from the main thread, + * because tevent_req_done() is not designed to be executed in + * the multithread environment, so tevent_req_done() must be + * executed from the smbd main thread. + * + * write(2) on pipes with sizes under _POSIX_PIPE_BUF + * in size is atomic, without this, the use op pipes in this + * code would not work. + * + * sys_write is a thin enough wrapper around write(2) + * that we can trust it here. + */ + + sts = sys_write(write_fd, &state, sizeof(struct glusterfs_aio_state *)); + if (sts < 0) { + DEBUG(0,("\nWrite to pipe failed (%s)", strerror(errno))); + } + + return; } -static ssize_t vfs_gluster_write(struct vfs_handle_struct *handle, - files_struct *fsp, const void *data, size_t n) +/* + * Read each req off the pipe and process it. + */ +static void aio_tevent_fd_done(struct tevent_context *event_ctx, + struct tevent_fd *fde, + uint16_t flags, void *data) { - return glfs_write(glfd_fd_get(fsp->fh->fd), data, n, 0); + struct tevent_req *req = NULL; + struct glusterfs_aio_state *state = NULL; + int sts = 0; + + /* + * read(2) on pipes is atomic if the needed data is available + * in the pipe, per SUS and POSIX. Because we always write + * to the pipe in sizeof(struct tevent_req *) chunks, we can + * always read in those chunks, atomically. + * + * sys_read is a thin enough wrapper around read(2) that we + * can trust it here. + */ + + sts = sys_read(read_fd, &state, sizeof(struct glusterfs_aio_state *)); + + if (sts < 0) { + DEBUG(0,("\nRead from pipe failed (%s)", strerror(errno))); + } + + /* if we've cancelled the op, there is no req, so just clean up. */ + if (state->cancelled == true) { + TALLOC_FREE(state); + return; + } + + req = state->req; + + if (req) { + tevent_req_done(req); + } + return; } -static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle, - files_struct *fsp, const void *data, - size_t n, off_t offset) +static bool init_gluster_aio(struct vfs_handle_struct *handle) { - return glfs_pwrite(glfd_fd_get(fsp->fh->fd), data, n, offset, 0); + int fds[2]; + int ret = -1; + + if (read_fd != -1) { + /* + * Already initialized. + */ + return true; + } + + ret = pipe(fds); + if (ret == -1) { + goto fail; + } + + read_fd = fds[0]; + write_fd = fds[1]; + + aio_read_event = tevent_add_fd(handle->conn->sconn->ev_ctx, + NULL, + read_fd, + TEVENT_FD_READ, + aio_tevent_fd_done, + NULL); + if (aio_read_event == NULL) { + goto fail; + } + + return true; +fail: + TALLOC_FREE(aio_read_event); + if (read_fd != -1) { + close(read_fd); + close(write_fd); + read_fd = -1; + write_fd = -1; + } + return false; +} + +static struct glusterfs_aio_state *aio_state_create(TALLOC_CTX *mem_ctx) +{ + struct tevent_req *req = NULL; + struct glusterfs_aio_state *state = NULL; + struct glusterfs_aio_wrapper *wrapper = NULL; + + req = tevent_req_create(mem_ctx, &wrapper, struct glusterfs_aio_wrapper); + + if (req == NULL) { + return NULL; + } + + state = talloc_zero(NULL, struct glusterfs_aio_state); + + if (state == NULL) { + TALLOC_FREE(req); + return NULL; + } + + talloc_set_destructor(wrapper, aio_wrapper_destructor); + state->cancelled = false; + state->req = req; + + wrapper->state = state; + + return state; +} + +static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct + *handle, TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + files_struct *fsp, + void *data, size_t n, + off_t offset) +{ + struct glusterfs_aio_state *state = NULL; + struct tevent_req *req = NULL; + int ret = 0; + + state = aio_state_create(mem_ctx); + + if (state == NULL) { + return NULL; + } + + req = state->req; + + if (!init_gluster_aio(handle)) { + tevent_req_error(req, EIO); + return tevent_req_post(req, ev); + } + + PROFILE_TIMESTAMP(&state->start); + ret = glfs_pread_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, + fsp), data, n, offset, 0, aio_glusterfs_done, + state); + if (ret < 0) { + tevent_req_error(req, -ret); + return tevent_req_post(req, ev); + } + + return req; } static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct @@ -541,20 +824,82 @@ static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct const void *data, size_t n, off_t offset) { - errno = ENOTSUP; - return NULL; + struct glusterfs_aio_state *state = NULL; + struct tevent_req *req = NULL; + int ret = 0; + + state = aio_state_create(mem_ctx); + + if (state == NULL) { + return NULL; + } + + req = state->req; + + if (!init_gluster_aio(handle)) { + tevent_req_error(req, EIO); + return tevent_req_post(req, ev); + } + + PROFILE_TIMESTAMP(&state->start); + ret = glfs_pwrite_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, + fsp), data, n, offset, 0, aio_glusterfs_done, + state); + if (ret < 0) { + tevent_req_error(req, -ret); + return tevent_req_post(req, ev); + } + + return req; } -static ssize_t vfs_gluster_pwrite_recv(struct tevent_req *req, int *err) +static ssize_t vfs_gluster_recv(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) { - errno = ENOTSUP; - return -1; + struct glusterfs_aio_wrapper *wrapper = NULL; + int ret = 0; + + wrapper = tevent_req_data(req, struct glusterfs_aio_wrapper); + + if (wrapper == NULL) { + return -1; + } + + if (wrapper->state == NULL) { + return -1; + } + + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { + return -1; + } + + *vfs_aio_state = wrapper->state->vfs_aio_state; + ret = wrapper->state->ret; + + /* Clean up the state, it is in a NULL context. */ + + TALLOC_FREE(wrapper->state); + + return ret; +} + +static ssize_t vfs_gluster_write(struct vfs_handle_struct *handle, + files_struct *fsp, const void *data, size_t n) +{ + return glfs_write(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), data, n, 0); +} + +static ssize_t vfs_gluster_pwrite(struct vfs_handle_struct *handle, + files_struct *fsp, const void *data, + size_t n, off_t offset) +{ + return glfs_pwrite(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), data, n, offset, 0); } static off_t vfs_gluster_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence) { - return glfs_lseek(glfd_fd_get(fsp->fh->fd), offset, whence); + return glfs_lseek(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), offset, whence); } static ssize_t vfs_gluster_sendfile(struct vfs_handle_struct *handle, int tofd, @@ -585,7 +930,7 @@ static int vfs_gluster_rename(struct vfs_handle_struct *handle, static int vfs_gluster_fsync(struct vfs_handle_struct *handle, files_struct *fsp) { - return glfs_fsync(glfd_fd_get(fsp->fh->fd)); + return glfs_fsync(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp)); } static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct @@ -593,14 +938,40 @@ static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct struct tevent_context *ev, files_struct *fsp) { - errno = ENOTSUP; - return NULL; + struct tevent_req *req = NULL; + struct glusterfs_aio_state *state = NULL; + int ret = 0; + + state = aio_state_create(mem_ctx); + + if (state == NULL) { + return NULL; + } + + req = state->req; + + if (!init_gluster_aio(handle)) { + tevent_req_error(req, EIO); + return tevent_req_post(req, ev); + } + + PROFILE_TIMESTAMP(&state->start); + ret = glfs_fsync_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, + fsp), aio_glusterfs_done, req); + if (ret < 0) { + tevent_req_error(req, -ret); + return tevent_req_post(req, ev); + } + return req; } -static int vfs_gluster_fsync_recv(struct tevent_req *req, int *err) +static int vfs_gluster_fsync_recv(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) { - errno = ENOTSUP; - return -1; + /* + * Use implicit conversion ssize_t->int + */ + return vfs_gluster_recv(req, vfs_aio_state); } static int vfs_gluster_stat(struct vfs_handle_struct *handle, @@ -626,7 +997,7 @@ static int vfs_gluster_fstat(struct vfs_handle_struct *handle, struct stat st; int ret; - ret = glfs_fstat(glfd_fd_get(fsp->fh->fd), &st); + ret = glfs_fstat(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), &st); if (ret == 0) { smb_stat_ex_from_stat(sbuf, &st); } @@ -668,44 +1039,52 @@ static int vfs_gluster_unlink(struct vfs_handle_struct *handle, } static int vfs_gluster_chmod(struct vfs_handle_struct *handle, - const char *path, mode_t mode) + const struct smb_filename *smb_fname, + mode_t mode) { - return glfs_chmod(handle->data, path, mode); + return glfs_chmod(handle->data, smb_fname->base_name, mode); } static int vfs_gluster_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode) { - return glfs_fchmod(glfd_fd_get(fsp->fh->fd), mode); + return glfs_fchmod(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), mode); } static int vfs_gluster_chown(struct vfs_handle_struct *handle, - const char *path, uid_t uid, gid_t gid) + const struct smb_filename *smb_fname, + uid_t uid, + gid_t gid) { - return glfs_chown(handle->data, path, uid, gid); + return glfs_chown(handle->data, smb_fname->base_name, uid, gid); } static int vfs_gluster_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid) { - return glfs_fchown(glfd_fd_get(fsp->fh->fd), uid, gid); + return glfs_fchown(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), uid, gid); } static int vfs_gluster_lchown(struct vfs_handle_struct *handle, - const char *path, uid_t uid, gid_t gid) + const struct smb_filename *smb_fname, + uid_t uid, + gid_t gid) { - return glfs_lchown(handle->data, path, uid, gid); + return glfs_lchown(handle->data, smb_fname->base_name, uid, gid); } -static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const char *path) +static int vfs_gluster_chdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - return glfs_chdir(handle->data, path); + return glfs_chdir(handle->data, smb_fname->base_name); } -static char *vfs_gluster_getwd(struct vfs_handle_struct *handle) +static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx) { char *cwd; char *ret; + struct smb_filename *smb_fname = NULL; cwd = SMB_CALLOC_ARRAY(char, PATH_MAX); if (cwd == NULL) { @@ -713,10 +1092,17 @@ static char *vfs_gluster_getwd(struct vfs_handle_struct *handle) } ret = glfs_getcwd(handle->data, cwd, PATH_MAX - 1); - if (ret == 0) { - free(cwd); + if (ret == NULL) { + SAFE_FREE(cwd); + return NULL; } - return ret; + smb_fname = synthetic_smb_fname(ctx, + ret, + NULL, + NULL, + 0); + SAFE_FREE(cwd); + return smb_fname; } static int vfs_gluster_ntimes(struct vfs_handle_struct *handle, @@ -725,10 +1111,28 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle, { struct timespec times[2]; - times[0].tv_sec = ft->atime.tv_sec; - times[0].tv_nsec = ft->atime.tv_nsec; - times[1].tv_sec = ft->mtime.tv_sec; - times[1].tv_nsec = ft->mtime.tv_nsec; + if (null_timespec(ft->atime)) { + times[0].tv_sec = smb_fname->st.st_ex_atime.tv_sec; + times[0].tv_nsec = smb_fname->st.st_ex_atime.tv_nsec; + } else { + times[0].tv_sec = ft->atime.tv_sec; + times[0].tv_nsec = ft->atime.tv_nsec; + } + + if (null_timespec(ft->mtime)) { + times[1].tv_sec = smb_fname->st.st_ex_mtime.tv_sec; + times[1].tv_nsec = smb_fname->st.st_ex_mtime.tv_nsec; + } else { + times[1].tv_sec = ft->mtime.tv_sec; + times[1].tv_nsec = ft->mtime.tv_nsec; + } + + if ((timespec_compare(×[0], + &smb_fname->st.st_ex_atime) == 0) && + (timespec_compare(×[1], + &smb_fname->st.st_ex_mtime) == 0)) { + return 0; + } return glfs_utimens(handle->data, smb_fname->base_name, times); } @@ -736,22 +1140,41 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle, static int vfs_gluster_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset) { - return glfs_ftruncate(glfd_fd_get(fsp->fh->fd), offset); + return glfs_ftruncate(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), offset); } static int vfs_gluster_fallocate(struct vfs_handle_struct *handle, struct files_struct *fsp, - enum vfs_fallocate_mode mode, + uint32_t mode, off_t offset, off_t len) { + /* TODO: add support using glfs_fallocate() and glfs_zerofill() */ errno = ENOTSUP; return -1; } -static char *vfs_gluster_realpath(struct vfs_handle_struct *handle, - const char *path) +static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - return glfs_realpath(handle->data, path, 0); + char *result = NULL; + struct smb_filename *result_fname = NULL; + char *resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1); + + if (resolved_path == NULL) { + errno = ENOMEM; + return NULL; + } + + result = glfs_realpath(handle->data, + smb_fname->base_name, + resolved_path); + if (result != NULL) { + result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0); + } + + SAFE_FREE(resolved_path); + return result_fname; } static bool vfs_gluster_lock(struct vfs_handle_struct *handle, @@ -767,7 +1190,7 @@ static bool vfs_gluster_lock(struct vfs_handle_struct *handle, flock.l_len = count; flock.l_pid = 0; - ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), op, &flock); + ret = glfs_posix_lock(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), op, &flock); if (op == F_GETLK) { /* lock query, true if someone else has locked */ @@ -787,7 +1210,7 @@ static bool vfs_gluster_lock(struct vfs_handle_struct *handle, } static int vfs_gluster_kernel_flock(struct vfs_handle_struct *handle, - files_struct *fsp, uint32 share_mode, + files_struct *fsp, uint32_t share_mode, uint32_t access_mask) { errno = ENOSYS; @@ -814,7 +1237,7 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle, flock.l_len = *pcount; flock.l_pid = 0; - ret = glfs_posix_lock(glfd_fd_get(fsp->fh->fd), F_GETLK, &flock); + ret = glfs_posix_lock(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), F_GETLK, &flock); if (ret == -1) { return false; @@ -829,43 +1252,42 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle, } static int vfs_gluster_symlink(struct vfs_handle_struct *handle, - const char *oldpath, const char *newpath) + const char *link_target, + const struct smb_filename *new_smb_fname) { - return glfs_symlink(handle->data, oldpath, newpath); + return glfs_symlink(handle->data, + link_target, + new_smb_fname->base_name); } static int vfs_gluster_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { - return glfs_readlink(handle->data, path, buf, bufsiz); + return glfs_readlink(handle->data, smb_fname->base_name, buf, bufsiz); } static int vfs_gluster_link(struct vfs_handle_struct *handle, - const char *oldpath, const char *newpath) + const struct smb_filename *old_smb_fname, + const struct smb_filename *new_smb_fname) { - return glfs_link(handle->data, oldpath, newpath); + return glfs_link(handle->data, + old_smb_fname->base_name, + new_smb_fname->base_name); } -static int vfs_gluster_mknod(struct vfs_handle_struct *handle, const char *path, - mode_t mode, SMB_DEV_T dev) +static int vfs_gluster_mknod(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode, + SMB_DEV_T dev) { - return glfs_mknod(handle->data, path, mode, dev); -} - -static NTSTATUS vfs_gluster_notify_watch(struct vfs_handle_struct *handle, - struct sys_notify_context *ctx, - const char *path, uint32_t *filter, - uint32_t *subdir_filter, - void (*callback) (struct sys_notify_context *ctx, - void *private_data, - struct notify_event *ev), - void *private_data, void *handle_p) -{ - return NT_STATUS_NOT_IMPLEMENTED; + return glfs_mknod(handle->data, smb_fname->base_name, mode, dev); } static int vfs_gluster_chflags(struct vfs_handle_struct *handle, - const char *path, unsigned int flags) + const struct smb_filename *smb_fname, + unsigned int flags) { errno = ENOSYS; return -1; @@ -885,7 +1307,7 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle, } snprintf(key_buf, NAME_MAX + 64, - "user.glusterfs.get_real_filename:%s", name); + "glusterfs.get_real_filename:%s", name); ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1); if (ret == -1) { @@ -904,7 +1326,7 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle, } static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle, - const char *filename) + const struct smb_filename *smb_fname) { return handle->conn->connectpath; } @@ -912,56 +1334,63 @@ static const char *vfs_gluster_connectpath(struct vfs_handle_struct *handle, /* EA Operations */ static ssize_t vfs_gluster_getxattr(struct vfs_handle_struct *handle, - const char *path, const char *name, - void *value, size_t size) + const struct smb_filename *smb_fname, + const char *name, + void *value, + size_t size) { - return glfs_getxattr(handle->data, path, name, value, size); + return glfs_getxattr(handle->data, smb_fname->base_name, + name, value, size); } static ssize_t vfs_gluster_fgetxattr(struct vfs_handle_struct *handle, files_struct *fsp, const char *name, void *value, size_t size) { - return glfs_fgetxattr(glfd_fd_get(fsp->fh->fd), name, value, size); + return glfs_fgetxattr(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), name, value, size); } static ssize_t vfs_gluster_listxattr(struct vfs_handle_struct *handle, - const char *path, char *list, size_t size) + const struct smb_filename *smb_fname, + char *list, + size_t size) { - return glfs_listxattr(handle->data, path, list, size); + return glfs_listxattr(handle->data, smb_fname->base_name, list, size); } static ssize_t vfs_gluster_flistxattr(struct vfs_handle_struct *handle, files_struct *fsp, char *list, size_t size) { - return glfs_flistxattr(glfd_fd_get(fsp->fh->fd), list, size); + return glfs_flistxattr(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), list, size); } static int vfs_gluster_removexattr(struct vfs_handle_struct *handle, - const char *path, const char *name) + const struct smb_filename *smb_fname, + const char *name) { - return glfs_removexattr(handle->data, path, name); + return glfs_removexattr(handle->data, smb_fname->base_name, name); } static int vfs_gluster_fremovexattr(struct vfs_handle_struct *handle, files_struct *fsp, const char *name) { - return glfs_fremovexattr(glfd_fd_get(fsp->fh->fd), name); + return glfs_fremovexattr(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), name); } static int vfs_gluster_setxattr(struct vfs_handle_struct *handle, - const char *path, const char *name, + const struct smb_filename *smb_fname, + const char *name, const void *value, size_t size, int flags) { - return glfs_setxattr(handle->data, path, name, value, size, flags); + return glfs_setxattr(handle->data, smb_fname->base_name, name, value, size, flags); } static int vfs_gluster_fsetxattr(struct vfs_handle_struct *handle, files_struct *fsp, const char *name, const void *value, size_t size, int flags) { - return glfs_fsetxattr(glfd_fd_get(fsp->fh->fd), name, value, size, + return glfs_fsetxattr(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), name, value, size, flags); } @@ -973,453 +1402,6 @@ static bool vfs_gluster_aio_force(struct vfs_handle_struct *handle, return false; } -/* Offline Operations */ - -static bool vfs_gluster_is_offline(struct vfs_handle_struct *handle, - const struct smb_filename *fname, - SMB_STRUCT_STAT *sbuf) -{ - return false; -} - -static int vfs_gluster_set_offline(struct vfs_handle_struct *handle, - const struct smb_filename *fname) -{ - errno = ENOTSUP; - return -1; -} - -/* - Gluster ACL Format: - - Size = 4 (header) + N * 8 (entry) - - Offset Size Field (Little Endian) - ------------------------------------- - 0-3 4-byte Version - - 4-5 2-byte Entry-1 tag - 6-7 2-byte Entry-1 perm - 8-11 4-byte Entry-1 id - - 12-13 2-byte Entry-2 tag - 14-15 2-byte Entry-2 perm - 16-19 4-byte Entry-2 id - - ... - - */ - -/* header version */ -#define GLUSTER_ACL_VERSION 2 - -/* perm bits */ -#define GLUSTER_ACL_READ 0x04 -#define GLUSTER_ACL_WRITE 0x02 -#define GLUSTER_ACL_EXECUTE 0x01 - -/* tag values */ -#define GLUSTER_ACL_UNDEFINED_TAG 0x00 -#define GLUSTER_ACL_USER_OBJ 0x01 -#define GLUSTER_ACL_USER 0x02 -#define GLUSTER_ACL_GROUP_OBJ 0x04 -#define GLUSTER_ACL_GROUP 0x08 -#define GLUSTER_ACL_MASK 0x10 -#define GLUSTER_ACL_OTHER 0x20 - -#define GLUSTER_ACL_UNDEFINED_ID (-1) - -#define GLUSTER_ACL_HEADER_SIZE 4 -#define GLUSTER_ACL_ENTRY_SIZE 8 - -static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size, - TALLOC_CTX *mem_ctx) -{ - int count; - size_t size; - struct smb_acl_entry *smb_ace; - struct smb_acl_t *result; - int i; - int offset; - uint16_t tag; - uint16_t perm; - uint32_t id; - - size = xattr_size; - - if (size < GLUSTER_ACL_HEADER_SIZE) { - /* ACL should be at least as big as the header (4 bytes) */ - errno = EINVAL; - return NULL; - } - - size -= GLUSTER_ACL_HEADER_SIZE; /* size of header = 4 bytes */ - - if (size % GLUSTER_ACL_ENTRY_SIZE) { - /* Size of entries must strictly be a multiple of - size of an ACE (8 bytes) - */ - errno = EINVAL; - return NULL; - } - - count = size / GLUSTER_ACL_ENTRY_SIZE; - - /* Version is the first 4 bytes of the ACL */ - if (IVAL(buf, 0) != GLUSTER_ACL_VERSION) { - DEBUG(0, ("Unknown gluster ACL version: %d\n", - IVAL(buf, 0))); - return NULL; - } - offset = GLUSTER_ACL_HEADER_SIZE; - - result = sys_acl_init(mem_ctx); - if (!result) { - errno = ENOMEM; - return NULL; - } - - result->acl = talloc_array(result, struct smb_acl_entry, count); - if (!result->acl) { - errno = ENOMEM; - talloc_free(result); - return NULL; - } - - result->count = count; - - smb_ace = result->acl; - - for (i = 0; i < count; i++) { - /* TAG is the first 2 bytes of an entry */ - tag = SVAL(buf, offset); - offset += 2; - - /* PERM is the next 2 bytes of an entry */ - perm = SVAL(buf, offset); - offset += 2; - - /* ID is the last 4 bytes of an entry */ - id = IVAL(buf, offset); - offset += 4; - - switch(tag) { - case GLUSTER_ACL_USER: - smb_ace->a_type = SMB_ACL_USER; - break; - case GLUSTER_ACL_USER_OBJ: - smb_ace->a_type = SMB_ACL_USER_OBJ; - break; - case GLUSTER_ACL_GROUP: - smb_ace->a_type = SMB_ACL_GROUP; - break; - case GLUSTER_ACL_GROUP_OBJ: - smb_ace->a_type = SMB_ACL_GROUP_OBJ; - break; - case GLUSTER_ACL_OTHER: - smb_ace->a_type = SMB_ACL_OTHER; - break; - case GLUSTER_ACL_MASK: - smb_ace->a_type = SMB_ACL_MASK; - break; - default: - DEBUG(0, ("unknown tag type %d\n", (unsigned int) tag)); - return NULL; - } - - - switch(smb_ace->a_type) { - case SMB_ACL_USER: - smb_ace->info.user.uid = id; - break; - case SMB_ACL_GROUP: - smb_ace->info.group.gid = id; - break; - default: - break; - } - - smb_ace->a_perm = 0; - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0); - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_WRITE) ? SMB_ACL_WRITE : 0); - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); - - smb_ace++; - } - - return result; -} - - -static int gluster_ace_cmp(const void *left, const void *right) -{ - int ret = 0; - uint16_t tag_left, tag_right; - uint32_t id_left, id_right; - - /* - Sorting precedence: - - - Smaller TAG values must be earlier. - - - Within same TAG, smaller identifiers must be earlier, E.g: - UID 0 entry must be earlier than UID 200 - GID 17 entry must be earlier than GID 19 - */ - - /* TAG is the first element in the entry */ - tag_left = SVAL(left, 0); - tag_right = SVAL(right, 0); - - ret = (tag_left - tag_right); - if (!ret) { - /* ID is the third element in the entry, after two short - integers (tag and perm), i.e at offset 4. - */ - id_left = IVAL(left, 4); - id_right = IVAL(right, 4); - ret = id_left - id_right; - } - - return ret; -} - - -static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len) -{ - ssize_t size; - struct smb_acl_entry *smb_ace; - int i; - int count; - uint16_t tag; - uint16_t perm; - uint32_t id; - int offset; - - count = theacl->count; - - size = GLUSTER_ACL_HEADER_SIZE + (count * GLUSTER_ACL_ENTRY_SIZE); - if (!buf) { - return size; - } - - if (len < size) { - errno = ERANGE; - return -1; - } - - smb_ace = theacl->acl; - - /* Version is the first 4 bytes of the ACL */ - SIVAL(buf, 0, GLUSTER_ACL_VERSION); - offset = GLUSTER_ACL_HEADER_SIZE; - - for (i = 0; i < count; i++) { - /* Calculate tag */ - switch(smb_ace->a_type) { - case SMB_ACL_USER: - tag = GLUSTER_ACL_USER; - break; - case SMB_ACL_USER_OBJ: - tag = GLUSTER_ACL_USER_OBJ; - break; - case SMB_ACL_GROUP: - tag = GLUSTER_ACL_GROUP; - break; - case SMB_ACL_GROUP_OBJ: - tag = GLUSTER_ACL_GROUP_OBJ; - break; - case SMB_ACL_OTHER: - tag = GLUSTER_ACL_OTHER; - break; - case SMB_ACL_MASK: - tag = GLUSTER_ACL_MASK; - break; - default: - DEBUG(0, ("Unknown tag value %d\n", - smb_ace->a_type)); - errno = EINVAL; - return -1; - } - - - /* Calculate id */ - switch(smb_ace->a_type) { - case SMB_ACL_USER: - id = smb_ace->info.user.uid; - break; - case SMB_ACL_GROUP: - id = smb_ace->info.group.gid; - break; - default: - id = GLUSTER_ACL_UNDEFINED_ID; - break; - } - - /* Calculate perm */ - perm = 0; - - perm |= - ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0); - perm |= - ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0); - perm |= - ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0); - - - /* TAG is the first 2 bytes of an entry */ - SSVAL(buf, offset, tag); - offset += 2; - - /* PERM is the next 2 bytes of an entry */ - SSVAL(buf, offset, perm); - offset += 2; - - /* ID is the last 4 bytes of an entry */ - SIVAL(buf, offset, id); - offset += 4; - - smb_ace++; - } - - /* Skip the header, sort @count number of 8-byte entries */ - qsort(buf+GLUSTER_ACL_HEADER_SIZE, count, GLUSTER_ACL_ENTRY_SIZE, - gluster_ace_cmp); - - return size; -} - - -static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle, - const char *path_p, - SMB_ACL_TYPE_T type, - TALLOC_CTX *mem_ctx) -{ - struct smb_acl_t *result; - char *buf; - const char *key; - ssize_t ret; - - switch (type) { - case SMB_ACL_TYPE_ACCESS: - key = "system.posix_acl_access"; - break; - case SMB_ACL_TYPE_DEFAULT: - key = "system.posix_acl_default"; - break; - default: - errno = EINVAL; - return NULL; - } - - ret = glfs_getxattr(handle->data, path_p, key, 0, 0); - if (ret <= 0) { - return NULL; - } - - buf = alloca(ret); - ret = glfs_getxattr(handle->data, path_p, key, buf, ret); - if (ret <= 0) { - return NULL; - } - - result = gluster_to_smb_acl(buf, ret, mem_ctx); - - return result; -} - -static SMB_ACL_T vfs_gluster_sys_acl_get_fd(struct vfs_handle_struct *handle, - struct files_struct *fsp, - TALLOC_CTX *mem_ctx) -{ - struct smb_acl_t *result; - int ret; - char *buf; - - ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd), - "system.posix_acl_access", 0, 0); - if (ret <= 0) { - return NULL; - } - - buf = alloca(ret); - ret = glfs_fgetxattr(glfd_fd_get(fsp->fh->fd), - "system.posix_acl_access", buf, ret); - if (ret <= 0) { - return NULL; - } - - result = gluster_to_smb_acl(buf, ret, mem_ctx); - - return result; -} - -static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle, - const char *name, - SMB_ACL_TYPE_T acltype, - SMB_ACL_T theacl) -{ - int ret; - const char *key; - char *buf; - ssize_t size; - - switch (acltype) { - case SMB_ACL_TYPE_ACCESS: - key = "system.posix_acl_access"; - break; - case SMB_ACL_TYPE_DEFAULT: - key = "system.posix_acl_default"; - break; - default: - errno = EINVAL; - return -1; - } - - size = smb_to_gluster_acl(theacl, 0, 0); - buf = alloca(size); - - size = smb_to_gluster_acl(theacl, buf, size); - if (size == -1) { - return -1; - } - - ret = glfs_setxattr(handle->data, name, key, buf, size, 0); - - return ret; -} - -static int vfs_gluster_sys_acl_set_fd(struct vfs_handle_struct *handle, - struct files_struct *fsp, - SMB_ACL_T theacl) -{ - int ret; - char *key; - char *buf; - ssize_t size; - - size = smb_to_gluster_acl(theacl, 0, 0); - buf = alloca(size); - - size = smb_to_gluster_acl(theacl, buf, size); - if (size == -1) { - return -1; - } - - ret = glfs_fsetxattr(glfd_fd_get(fsp->fh->fd), - "system.posix_acl_access", buf, size, 0); - return ret; -} - -static int vfs_gluster_sys_acl_delete_def_file(struct vfs_handle_struct *handle, - const char *path) -{ - return glfs_removexattr(handle->data, path, "system.posix_acl_default"); -} - static struct vfs_fn_pointers glusterfs_fns = { /* Disk Operations */ @@ -1445,7 +1427,6 @@ static struct vfs_fn_pointers glusterfs_fns = { .mkdir_fn = vfs_gluster_mkdir, .rmdir_fn = vfs_gluster_rmdir, .closedir_fn = vfs_gluster_closedir, - .init_search_op_fn = vfs_gluster_init_search_op, /* File Operations */ @@ -1455,11 +1436,11 @@ static struct vfs_fn_pointers glusterfs_fns = { .read_fn = vfs_gluster_read, .pread_fn = vfs_gluster_pread, .pread_send_fn = vfs_gluster_pread_send, - .pread_recv_fn = vfs_gluster_pread_recv, + .pread_recv_fn = vfs_gluster_recv, .write_fn = vfs_gluster_write, .pwrite_fn = vfs_gluster_pwrite, .pwrite_send_fn = vfs_gluster_pwrite_send, - .pwrite_recv_fn = vfs_gluster_pwrite_recv, + .pwrite_recv_fn = vfs_gluster_recv, .lseek_fn = vfs_gluster_lseek, .sendfile_fn = vfs_gluster_sendfile, .recvfile_fn = vfs_gluster_recvfile, @@ -1493,11 +1474,8 @@ static struct vfs_fn_pointers glusterfs_fns = { .link_fn = vfs_gluster_link, .mknod_fn = vfs_gluster_mknod, .realpath_fn = vfs_gluster_realpath, - .notify_watch_fn = vfs_gluster_notify_watch, .chflags_fn = vfs_gluster_chflags, .file_id_create_fn = NULL, - .copy_chunk_send_fn = NULL, - .copy_chunk_recv_fn = NULL, .streaminfo_fn = NULL, .get_real_filename_fn = vfs_gluster_get_real_filename, .connectpath_fn = vfs_gluster_connectpath, @@ -1505,8 +1483,7 @@ static struct vfs_fn_pointers glusterfs_fns = { .brl_lock_windows_fn = NULL, .brl_unlock_windows_fn = NULL, .brl_cancel_windows_fn = NULL, - .strict_lock_fn = NULL, - .strict_unlock_fn = NULL, + .strict_lock_check_fn = NULL, .translate_name_fn = NULL, .fsctl_fn = NULL, @@ -1519,13 +1496,13 @@ static struct vfs_fn_pointers glusterfs_fns = { /* Posix ACL Operations */ .chmod_acl_fn = NULL, /* passthrough to default */ .fchmod_acl_fn = NULL, /* passthrough to default */ - .sys_acl_get_file_fn = vfs_gluster_sys_acl_get_file, - .sys_acl_get_fd_fn = vfs_gluster_sys_acl_get_fd, + .sys_acl_get_file_fn = posixacl_xattr_acl_get_file, + .sys_acl_get_fd_fn = posixacl_xattr_acl_get_fd, .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file, .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd, - .sys_acl_set_file_fn = vfs_gluster_sys_acl_set_file, - .sys_acl_set_fd_fn = vfs_gluster_sys_acl_set_fd, - .sys_acl_delete_def_file_fn = vfs_gluster_sys_acl_delete_def_file, + .sys_acl_set_file_fn = posixacl_xattr_acl_set_file, + .sys_acl_set_fd_fn = posixacl_xattr_acl_set_fd, + .sys_acl_delete_def_file_fn = posixacl_xattr_acl_delete_def_file, /* EA Operations */ .getxattr_fn = vfs_gluster_getxattr, @@ -1540,18 +1517,14 @@ static struct vfs_fn_pointers glusterfs_fns = { /* AIO Operations */ .aio_force_fn = vfs_gluster_aio_force, - /* Offline Operations */ - .is_offline_fn = vfs_gluster_is_offline, - .set_offline_fn = vfs_gluster_set_offline, - /* Durable handle Operations */ .durable_cookie_fn = NULL, .durable_disconnect_fn = NULL, .durable_reconnect_fn = NULL, }; -NTSTATUS vfs_glusterfs_init(void); -NTSTATUS vfs_glusterfs_init(void) +NTSTATUS vfs_glusterfs_init(TALLOC_CTX *); +NTSTATUS vfs_glusterfs_init(TALLOC_CTX *ctx) { return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "glusterfs", &glusterfs_fns);