diff options
Diffstat (limited to 'source3/modules/vfs_tsmsm.c')
-rw-r--r-- | source3/modules/vfs_tsmsm.c | 171 |
1 files changed, 145 insertions, 26 deletions
diff --git a/source3/modules/vfs_tsmsm.c b/source3/modules/vfs_tsmsm.c index d53d291832..e4bc7eb454 100644 --- a/source3/modules/vfs_tsmsm.c +++ b/source3/modules/vfs_tsmsm.c @@ -27,7 +27,7 @@ where <operation> is currently 'offline' to set offline status of the <filepath> tsmsm: online ratio = ratio to check reported size against actual file size (0.5 by default) - tsmsm: attribute name = name of DMAPI attribute that is present when a file is offline. + tsmsm: dmapi attribute = name of DMAPI attribute that is present when a file is offline. Default is "IBMobj" (which is what GPFS uses) The TSMSM VFS module tries to avoid calling expensive DMAPI calls with some heuristics @@ -40,6 +40,7 @@ #include "includes.h" #include "smbd/smbd.h" +#include "lib/util/tevent_unix.h" #ifndef USE_DMAPI #error "This module requires DMAPI support!" @@ -97,7 +98,7 @@ static int tsmsm_connect(struct vfs_handle_struct *handle, return ret; } - tsmd = TALLOC_ZERO_P(handle, struct tsmsm_struct); + tsmd = talloc_zero(handle, struct tsmsm_struct); if (!tsmd) { SMB_VFS_NEXT_DISCONNECT(handle); DEBUG(0,("tsmsm_connect: out of memory!\n")); @@ -114,16 +115,19 @@ static int tsmsm_connect(struct vfs_handle_struct *handle, tsmname = (handle->param ? handle->param : "tsmsm"); /* Get 'hsm script' and 'dmapi attribute' parameters to tsmd context */ - tsmd->hsmscript = lp_parm_talloc_string(SNUM(handle->conn), tsmname, - "hsm script", NULL); + tsmd->hsmscript = lp_parm_talloc_string( + tsmd, SNUM(handle->conn), tsmname, + "hsm script", NULL); talloc_steal(tsmd, tsmd->hsmscript); - tsmd->attrib_name = lp_parm_talloc_string(SNUM(handle->conn), tsmname, - "dmapi attribute", DM_ATTRIB_OBJECT); + tsmd->attrib_name = lp_parm_talloc_string( + tsmd, SNUM(handle->conn), tsmname, + "dmapi attribute", DM_ATTRIB_OBJECT); talloc_steal(tsmd, tsmd->attrib_name); - tsmd->attrib_value = lp_parm_talloc_string(SNUM(handle->conn), "tsmsm", - "dmapi value", NULL); + tsmd->attrib_value = lp_parm_talloc_string( + tsmd, SNUM(handle->conn), tsmname, + "dmapi value", NULL); talloc_steal(tsmd, tsmd->attrib_value); /* retrieve 'online ratio'. In case of error default to FILE_IS_ONLINE_RATIO */ @@ -282,23 +286,135 @@ static bool tsmsm_aio_force(struct vfs_handle_struct *handle, struct files_struc return false; } -static ssize_t tsmsm_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, - SMB_STRUCT_AIOCB *aiocb) +struct tsmsm_pread_state { + struct files_struct *fsp; + ssize_t ret; + int err; + bool was_offline; +}; + +static void tsmsm_pread_done(struct tevent_req *subreq); + +static struct tevent_req *tsmsm_pread_send(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct files_struct *fsp, + void *data, size_t n, off_t offset) { - ssize_t result; + struct tevent_req *req, *subreq; + struct tsmsm_pread_state *state; - result = SMB_VFS_NEXT_AIO_RETURN(handle, fsp, aiocb); - if(result >= 0) { - notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED, + req = tevent_req_create(mem_ctx, &state, struct tsmsm_pread_state); + if (req == NULL) { + return NULL; + } + state->fsp = fsp; + state->was_offline = tsmsm_aio_force(handle, fsp); + subreq = SMB_VFS_NEXT_PREAD_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, tsmsm_pread_done, req); + return req; +} + +static void tsmsm_pread_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct tsmsm_pread_state *state = tevent_req_data( + req, struct tsmsm_pread_state); + + state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err); + TALLOC_FREE(subreq); + tevent_req_done(req); +} + +static ssize_t tsmsm_pread_recv(struct tevent_req *req, int *err) +{ + struct tsmsm_pread_state *state = tevent_req_data( + req, struct tsmsm_pread_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + if (state->ret >= 0 && state->was_offline) { + struct files_struct *fsp = state->fsp; + notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fsp->fsp_name->base_name); } + *err = state->err; + return state->ret; +} - return result; +struct tsmsm_pwrite_state { + struct files_struct *fsp; + ssize_t ret; + int err; + bool was_offline; +}; + +static void tsmsm_pwrite_done(struct tevent_req *subreq); + +static struct tevent_req *tsmsm_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) +{ + struct tevent_req *req, *subreq; + struct tsmsm_pwrite_state *state; + + req = tevent_req_create(mem_ctx, &state, struct tsmsm_pwrite_state); + if (req == NULL) { + return NULL; + } + state->fsp = fsp; + state->was_offline = tsmsm_aio_force(handle, fsp); + 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, tsmsm_pwrite_done, req); + return req; +} + +static void tsmsm_pwrite_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct tsmsm_pwrite_state *state = tevent_req_data( + req, struct tsmsm_pwrite_state); + + state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err); + TALLOC_FREE(subreq); + tevent_req_done(req); +} + +static ssize_t tsmsm_pwrite_recv(struct tevent_req *req, int *err) +{ + struct tsmsm_pwrite_state *state = tevent_req_data( + req, struct tsmsm_pwrite_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + if (state->ret >= 0 && state->was_offline) { + struct files_struct *fsp = state->fsp; + notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, + fsp->fsp_name->base_name); + } + *err = state->err; + return state->ret; } static ssize_t tsmsm_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, const DATA_BLOB *hdr, - SMB_OFF_T offset, size_t n) + off_t offset, size_t n) { bool file_offline = tsmsm_aio_force(handle, fsp); @@ -314,7 +430,7 @@ static ssize_t tsmsm_sendfile(vfs_handle_struct *handle, int tofd, files_struct /* We do overload pread to allow notification when file becomes online after offline status */ /* We don't intercept SMB_VFS_READ here because all file I/O now goes through SMB_VFS_PREAD instead */ static ssize_t tsmsm_pread(struct vfs_handle_struct *handle, struct files_struct *fsp, - void *data, size_t n, SMB_OFF_T offset) { + void *data, size_t n, off_t offset) { ssize_t result; bool notify_online = tsmsm_aio_force(handle, fsp); @@ -332,7 +448,7 @@ static ssize_t tsmsm_pread(struct vfs_handle_struct *handle, struct files_struct } static ssize_t tsmsm_pwrite(struct vfs_handle_struct *handle, struct files_struct *fsp, - const void *data, size_t n, SMB_OFF_T offset) { + const void *data, size_t n, off_t offset) { ssize_t result; bool notify_online = tsmsm_aio_force(handle, fsp); @@ -392,14 +508,17 @@ static uint32_t tsmsm_fs_capabilities(struct vfs_handle_struct *handle, static struct vfs_fn_pointers tsmsm_fns = { .connect_fn = tsmsm_connect, - .fs_capabilities = tsmsm_fs_capabilities, - .aio_force = tsmsm_aio_force, - .aio_return_fn = tsmsm_aio_return, - .pread = tsmsm_pread, - .pwrite = tsmsm_pwrite, - .sendfile = tsmsm_sendfile, - .is_offline = tsmsm_is_offline, - .set_offline = tsmsm_set_offline, + .fs_capabilities_fn = tsmsm_fs_capabilities, + .aio_force_fn = tsmsm_aio_force, + .pread_fn = tsmsm_pread, + .pread_send_fn = tsmsm_pread_send, + .pread_recv_fn = tsmsm_pread_recv, + .pwrite_fn = tsmsm_pwrite, + .pwrite_send_fn = tsmsm_pwrite_send, + .pwrite_recv_fn = tsmsm_pwrite_recv, + .sendfile_fn = tsmsm_sendfile, + .is_offline_fn = tsmsm_is_offline, + .set_offline_fn = tsmsm_set_offline, }; NTSTATUS vfs_tsmsm_init(void); |