X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fmodules%2Fvfs_commit.c;h=cade1170bab445801c31959937710f6e385821c6;hb=HEAD;hp=c22e8161d70d561987c51b2505e31fe62342a26f;hpb=5ab03dbecc33320e23304b126f26bde3f6bc6c7d;p=samba.git diff --git a/source3/modules/vfs_commit.c b/source3/modules/vfs_commit.c index c22e8161d70..355edeac13a 100644 --- a/source3/modules/vfs_commit.c +++ b/source3/modules/vfs_commit.c @@ -17,6 +17,9 @@ */ #include "includes.h" +#include "system/filesys.h" +#include "smbd/smbd.h" +#include "lib/util/tevent_unix.h" /* Commit data module. * @@ -42,7 +45,7 @@ * size of the file before transferring it. With this * option, we remember that hint, and commit after * writing in that file position. If the client - * doesn't declare the size of file, commiting on EOF + * doesn't declare the size of file, committing on EOF * is not triggered. * * = growth Commits after a write operation has made the file @@ -66,11 +69,11 @@ enum eof_mode struct commit_info { /* For chunk-based commits */ - SMB_OFF_T dbytes; /* Dirty (uncommitted) bytes */ - SMB_OFF_T dthresh; /* Dirty data threshold */ + off_t dbytes; /* Dirty (uncommitted) bytes */ + off_t dthresh; /* Dirty data threshold */ /* For commits on EOF */ enum eof_mode on_eof; - SMB_OFF_T eof; /* Expected file size */ + off_t eof; /* Expected file size */ }; static int commit_do( @@ -83,11 +86,13 @@ static int commit_do( ("%s: flushing %lu dirty bytes\n", MODULE, (unsigned long)c->dbytes)); -#if HAVE_FDATASYNC +#if defined(HAVE_FDATASYNC) result = fdatasync(fd); -#elif HAVE_FSYNC +#elif defined(HAVE_FSYNC) result = fsync(fd); #else + DEBUG(0, ("%s: WARNING: no commit support on this platform\n", + MODULE)); result = 0 #endif if (result == 0) { @@ -102,13 +107,13 @@ static int commit_all( { struct commit_info *c; - if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { + if ((c = (struct commit_info *)VFS_FETCH_FSP_EXTENSION(handle, fsp))) { if (c->dbytes) { DEBUG(module_debug, ("%s: flushing %lu dirty bytes\n", MODULE, (unsigned long)c->dbytes)); - return commit_do(c, fsp->fh->fd); + return commit_do(c, fsp_get_io_fd(fsp)); } } return 0; @@ -117,19 +122,20 @@ static int commit_all( static int commit( struct vfs_handle_struct * handle, files_struct * fsp, - SMB_OFF_T offset, + off_t offset, ssize_t last_write) { struct commit_info *c; - if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp)) == NULL) { + if ((c = (struct commit_info *)VFS_FETCH_FSP_EXTENSION(handle, fsp)) + == NULL) { return 0; } c->dbytes += last_write; /* dirty bytes always counted */ if (c->dthresh && (c->dbytes > c->dthresh)) { - return commit_do(c, fsp->fh->fd); + return commit_do(c, fsp_get_io_fd(fsp)); } /* Return if we are not in EOF mode or if we have temporarily opted @@ -141,7 +147,7 @@ static int commit( /* This write hit or went past our cache the file size. */ if ((offset + last_write) >= c->eof) { - if (commit_do(c, fsp->fh->fd) == -1) { + if (commit_do(c, fsp_get_io_fd(fsp)) == -1) { return -1; } @@ -161,25 +167,34 @@ static int commit_connect( const char * service, const char * user) { + int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); + + if (ret < 0) { + return ret; + } + module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100); - return SMB_VFS_NEXT_CONNECT(handle, service, user); + return 0; } -static int commit_open( - vfs_handle_struct * handle, - const char * fname, - files_struct * fsp, - int flags, - mode_t mode) +static int commit_openat(struct vfs_handle_struct *handle, + const struct files_struct *dirfsp, + const struct smb_filename *smb_fname, + files_struct *fsp, + const struct vfs_open_how *how) { - SMB_OFF_T dthresh; + off_t dthresh; const char *eof_mode; struct commit_info *c = NULL; int fd; /* Don't bother with read-only files. */ - if ((flags & O_ACCMODE) == O_RDONLY) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + if ((how->flags & O_ACCMODE) == O_RDONLY) { + return SMB_VFS_NEXT_OPENAT(handle, + dirfsp, + smb_fname, + fsp, + how); } /* Read and check module configuration */ @@ -190,7 +205,8 @@ static int commit_open( MODULE, "eof mode", "none"); if (dthresh > 0 || !strequal(eof_mode, "none")) { - c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info, NULL); + c = VFS_ADD_FSP_EXTENSION( + handle, fsp, struct commit_info, NULL); /* Process main tunables */ if (c) { c->dthresh = dthresh; @@ -208,7 +224,7 @@ static int commit_open( } } - fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + fd = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, how); if (fd == -1) { VFS_REMOVE_FSP_EXTENSION(handle, fsp); return fd; @@ -217,26 +233,37 @@ static int commit_open( /* EOF commit modes require us to know the initial file size. */ if (c && (c->on_eof != EOF_NONE)) { SMB_STRUCT_STAT st; - if (SMB_VFS_FSTAT(fsp, &st) == -1) { + /* + * Setting the fd of the FSP is a hack + * but also practiced elsewhere - + * needed for calling the VFS. + */ + fsp_set_fd(fsp, fd); + if (SMB_VFS_FSTAT(fsp, &st) == -1) { + int saved_errno = errno; + SMB_VFS_CLOSE(fsp); + fsp_set_fd(fsp, -1); + errno = saved_errno; return -1; } c->eof = st.st_ex_size; } - return 0; + return fd; } -static ssize_t commit_write( +static ssize_t commit_pwrite( vfs_handle_struct * handle, files_struct * fsp, - void * data, - size_t count) + const void * data, + size_t count, + off_t offset) { ssize_t ret; - ret = SMB_VFS_NEXT_WRITE(handle, fsp, data, count); + ret = SMB_VFS_NEXT_PWRITE(handle, fsp, data, count, offset); if (ret > 0) { - if (commit(handle, fsp, fsp->fh->pos, ret) == -1) { + if (commit(handle, fsp, offset, ret) == -1) { return -1; } } @@ -244,23 +271,84 @@ static ssize_t commit_write( return ret; } -static ssize_t commit_pwrite( - vfs_handle_struct * handle, - files_struct * fsp, - void * data, - size_t count, - SMB_OFF_T offset) +struct commit_pwrite_state { + struct vfs_handle_struct *handle; + struct files_struct *fsp; + ssize_t ret; + struct vfs_aio_state vfs_aio_state; +}; + +static void commit_pwrite_written(struct tevent_req *subreq); + +static struct tevent_req *commit_pwrite_send(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct files_struct *fsp, + const void *data, + size_t n, off_t offset) { - ssize_t ret; + struct tevent_req *req, *subreq; + struct commit_pwrite_state *state; - ret = SMB_VFS_NEXT_PWRITE(handle, fsp, data, count, offset); - if (ret > 0) { - if (commit(handle, fsp, offset, ret) == -1) { - return -1; - } - } + req = tevent_req_create(mem_ctx, &state, struct commit_pwrite_state); + if (req == NULL) { + return NULL; + } + state->handle = handle; + state->fsp = fsp; - return ret; + subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data, + n, offset); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, commit_pwrite_written, req); + return req; +} + +static void commit_pwrite_written(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct commit_pwrite_state *state = tevent_req_data( + req, struct commit_pwrite_state); + int commit_ret; + + state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state); + TALLOC_FREE(subreq); + + if (state->ret <= 0) { + tevent_req_done(req); + return; + } + + /* + * Ok, this is a sync fake. We should make the sync async as well, but + * I'm too lazy for that right now -- vl + */ + commit_ret = commit(state->handle, + state->fsp, + fh_get_pos(state->fsp->fh), + state->ret); + + if (commit_ret == -1) { + state->ret = -1; + } + + tevent_req_done(req); +} + +static ssize_t commit_pwrite_recv(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) +{ + struct commit_pwrite_state *state = + tevent_req_data(req, struct commit_pwrite_state); + + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { + return -1; + } + *vfs_aio_state = state->vfs_aio_state; + return state->ret; } static int commit_close( @@ -275,14 +363,15 @@ static int commit_close( static int commit_ftruncate( vfs_handle_struct * handle, files_struct * fsp, - SMB_OFF_T len) + off_t len) { int result; result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len); if (result == 0) { struct commit_info *c; - if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { + if ((c = (struct commit_info *)VFS_FETCH_FSP_EXTENSION( + handle, fsp))) { commit(handle, fsp, len, 0); c->eof = len; } @@ -291,28 +380,21 @@ static int commit_ftruncate( return result; } -static vfs_op_tuple commit_ops [] = -{ - {SMB_VFS_OP(commit_open), - SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(commit_close), - SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(commit_write), - SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(commit_pwrite), - SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(commit_connect), - SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(commit_ftruncate), - SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT}, - - {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +static struct vfs_fn_pointers vfs_commit_fns = { + .openat_fn = commit_openat, + .close_fn = commit_close, + .pwrite_fn = commit_pwrite, + .pwrite_send_fn = commit_pwrite_send, + .pwrite_recv_fn = commit_pwrite_recv, + .connect_fn = commit_connect, + .ftruncate_fn = commit_ftruncate }; -NTSTATUS vfs_commit_init(void); -NTSTATUS vfs_commit_init(void) +static_decl_vfs; +NTSTATUS vfs_commit_init(TALLOC_CTX *ctx) { - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops); + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, + &vfs_commit_fns); }