diff options
Diffstat (limited to 'xlators/performance/write-behind/src/write-behind.c')
-rw-r--r-- | xlators/performance/write-behind/src/write-behind.c | 1364 |
1 files changed, 768 insertions, 596 deletions
diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c index ddd8a6ba244..2cec7132431 100644 --- a/xlators/performance/write-behind/src/write-behind.c +++ b/xlators/performance/write-behind/src/write-behind.c @@ -35,24 +35,28 @@ typedef struct list_head list_head_t; struct wb_conf; struct wb_page; -struct wb_file; +struct wb_inode; -typedef struct wb_file { - int disabled; - uint64_t disable_till; +typedef struct wb_inode { size_t window_conf; size_t window_current; - int32_t flags; size_t aggregate_current; - int32_t refcount; int32_t op_ret; int32_t op_errno; list_head_t request; list_head_t passive_requests; - fd_t *fd; gf_lock_t lock; xlator_t *this; -}wb_file_t; +}wb_inode_t; + +typedef struct wb_file { + int32_t flags; + int disabled; + fd_t *fd; + size_t disable_till; + enum _gf_boolean dont_wind; +} wb_file_t; + typedef struct wb_request { list_head_t list; @@ -62,7 +66,7 @@ typedef struct wb_request { call_stub_t *stub; size_t write_size; int32_t refcount; - wb_file_t *file; + wb_inode_t *wb_inode; glusterfs_fop_t fop; gf_lkowner_t lk_owner; union { @@ -99,27 +103,90 @@ struct wb_conf { typedef struct wb_local { list_head_t winds; int32_t flags; - struct wb_file *file; + fd_t *fd; wb_request_t *request; int op_ret; int op_errno; call_frame_t *frame; int32_t reply_count; + wb_inode_t *wb_inode; } wb_local_t; typedef struct wb_conf wb_conf_t; typedef struct wb_page wb_page_t; int32_t -wb_process_queue (call_frame_t *frame, wb_file_t *file); +wb_process_queue (call_frame_t *frame, wb_inode_t *wb_inode); ssize_t -wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds); +wb_sync (call_frame_t *frame, wb_inode_t *wb_inode, list_head_t *winds); ssize_t __wb_mark_winds (list_head_t *list, list_head_t *winds, size_t aggregate_size, char enable_trickling_writes); +wb_inode_t * +__wb_inode_ctx_get (xlator_t *this, inode_t *inode) +{ + uint64_t value = 0; + wb_inode_t *wb_inode = NULL; + + __inode_ctx_get (inode, this, &value); + wb_inode = (wb_inode_t *)(unsigned long) value; + + return wb_inode; +} + + +wb_inode_t * +wb_inode_ctx_get (xlator_t *this, inode_t *inode) +{ + wb_inode_t *wb_inode = NULL; + + GF_VALIDATE_OR_GOTO ("write-behind", this, out); + GF_VALIDATE_OR_GOTO (this->name, inode, out); + + LOCK (&inode->lock); + { + wb_inode = __wb_inode_ctx_get (this, inode); + } + UNLOCK (&inode->lock); +out: + return wb_inode; +} + + +wb_file_t * +__wb_fd_ctx_get (xlator_t *this, fd_t *fd) +{ + wb_file_t *wb_file = NULL; + uint64_t value = 0; + + fd_ctx_get (fd, this, &value); + wb_file = (wb_file_t *)(unsigned long)value; + + return wb_file; +} + + +wb_file_t * +wb_fd_ctx_get (xlator_t *this, fd_t *fd) +{ + wb_file_t *wb_file = NULL; + + GF_VALIDATE_OR_GOTO ("write-behind", this, out); + GF_VALIDATE_OR_GOTO (this->name, fd, out); + + LOCK (&fd->lock); + { + wb_file = __wb_fd_ctx_get (this, fd); + } + UNLOCK (&fd->lock); + +out: + return wb_file; +} + /* Below is a succinct explanation of the code deciding whether two regions overlap, from Pavan <tcp@gluster.com>. @@ -147,7 +214,8 @@ __wb_mark_winds (list_head_t *list, list_head_t *winds, size_t aggregate_size, static inline char wb_requests_overlap (wb_request_t *request1, wb_request_t *request2) { - off_t r1_start = 0, r1_end = 0, r2_start = 0, r2_end = 0; + off_t r1_start = 0, r1_end = 0, r2_start = 0, r2_end = 0; + enum _gf_boolean do_overlap = 0; r1_start = request1->stub->args.writev.off; r1_end = r1_start + iov_length (request1->stub->args.writev.vector, @@ -157,7 +225,9 @@ wb_requests_overlap (wb_request_t *request1, wb_request_t *request2) r2_end = r2_start + iov_length (request2->stub->args.writev.vector, request2->stub->args.writev.count); - return ((r1_end >= r2_start) && (r2_end >= r1_start)); + do_overlap = ((r1_end >= r2_start) && (r2_end >= r1_start)); + + return do_overlap; } @@ -217,18 +287,18 @@ out: static int wb_request_unref (wb_request_t *this) { - wb_file_t *file = NULL; - int ret = -1; + wb_inode_t *wb_inode = NULL; + int ret = -1; GF_VALIDATE_OR_GOTO ("write-behind", this, out); - file = this->file; + wb_inode = this->wb_inode; - LOCK (&file->lock); + LOCK (&wb_inode->lock); { ret = __wb_request_unref (this); } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); out: return ret; @@ -257,16 +327,16 @@ out: wb_request_t * wb_request_ref (wb_request_t *this) { - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; GF_VALIDATE_OR_GOTO ("write-behind", this, out); - file = this->file; - LOCK (&file->lock); + wb_inode = this->wb_inode; + LOCK (&wb_inode->lock); { this = __wb_request_ref (this); } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); out: return this; @@ -274,7 +344,7 @@ out: wb_request_t * -wb_enqueue (wb_file_t *file, call_stub_t *stub) +wb_enqueue (wb_inode_t *wb_inode, call_stub_t *stub) { wb_request_t *request = NULL, *tmp = NULL; call_frame_t *frame = NULL; @@ -282,8 +352,8 @@ wb_enqueue (wb_file_t *file, call_stub_t *stub) struct iovec *vector = NULL; int32_t count = 0; - GF_VALIDATE_OR_GOTO ("write-behind", file, out); - GF_VALIDATE_OR_GOTO (file->this->name, stub, out); + GF_VALIDATE_OR_GOTO ("write-behind", wb_inode, out); + GF_VALIDATE_OR_GOTO (wb_inode->this->name, stub, out); request = GF_CALLOC (1, sizeof (*request), gf_wb_mt_wb_request_t); if (request == NULL) { @@ -296,7 +366,7 @@ wb_enqueue (wb_file_t *file, call_stub_t *stub) INIT_LIST_HEAD (&request->other_requests); request->stub = stub; - request->file = file; + request->wb_inode = wb_inode; request->fop = stub->fop; frame = stub->frame; @@ -320,9 +390,9 @@ wb_enqueue (wb_file_t *file, call_stub_t *stub) request->lk_owner = frame->root->lk_owner; - LOCK (&file->lock); + LOCK (&wb_inode->lock); { - list_add_tail (&request->list, &file->request); + list_add_tail (&request->list, &wb_inode->request); if (stub->fop == GF_FOP_WRITE) { /* reference for stack winding */ __wb_request_ref (request); @@ -330,9 +400,9 @@ wb_enqueue (wb_file_t *file, call_stub_t *stub) /* reference for stack unwinding */ __wb_request_ref (request); - file->aggregate_current += request->write_size; + wb_inode->aggregate_current += request->write_size; } else { - list_for_each_entry (tmp, &file->request, list) { + list_for_each_entry (tmp, &wb_inode->request, list) { if (tmp->stub && tmp->stub->fop == GF_FOP_WRITE) { tmp->flags.write_request.flush_all = 1; @@ -343,13 +413,45 @@ wb_enqueue (wb_file_t *file, call_stub_t *stub) __wb_request_ref (request); } } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); out: return request; } +wb_inode_t * +__wb_inode_create (xlator_t *this, inode_t *inode) +{ + wb_inode_t *wb_inode = NULL; + wb_conf_t *conf = NULL; + + GF_VALIDATE_OR_GOTO ("write-behind", this, out); + GF_VALIDATE_OR_GOTO (this->name, inode, out); + + conf = this->private; + + wb_inode = GF_CALLOC (1, sizeof (*wb_inode), gf_wb_mt_wb_inode_t); + if (wb_inode == NULL) { + goto out; + } + + INIT_LIST_HEAD (&wb_inode->request); + INIT_LIST_HEAD (&wb_inode->passive_requests); + + wb_inode->this = this; + + wb_inode->window_conf = conf->window_size; + + LOCK_INIT (&wb_inode->lock); + + __inode_ctx_put (inode, this, (uint64_t)(unsigned long)wb_inode); + +out: + return wb_inode; +} + + wb_file_t * wb_file_create (xlator_t *this, fd_t *fd, int32_t flags) { @@ -366,60 +468,105 @@ wb_file_create (xlator_t *this, fd_t *fd, int32_t flags) goto out; } - INIT_LIST_HEAD (&file->request); - INIT_LIST_HEAD (&file->passive_requests); - /* fd_ref() not required, file should never decide the existence of an fd */ file->fd= fd; - file->disable_till = conf->disable_till; - file->this = this; - file->refcount = 1; - file->window_conf = conf->window_size; - file->flags = flags; + /* If O_DIRECT then, we disable chaching */ + if (((flags & O_DIRECT) == O_DIRECT) + || ((flags & O_ACCMODE) == O_RDONLY) + || (((flags & O_SYNC) == O_SYNC) + && conf->enable_O_SYNC == _gf_true)) { + file->disabled = 1; + } - LOCK_INIT (&file->lock); + file->flags = flags; - fd_ctx_set (fd, this, (uint64_t)(long)file); + fd_ctx_set (fd, this, (uint64_t)(unsigned long)file); out: return file; } -void -wb_file_destroy (wb_file_t *file) +wb_inode_t * +wb_inode_create (xlator_t *this, inode_t *inode) { - int32_t refcount = 0; + wb_inode_t *wb_inode = NULL; - GF_VALIDATE_OR_GOTO ("write-behind", file, out); + GF_VALIDATE_OR_GOTO ("write-behind", this, out); + GF_VALIDATE_OR_GOTO (this->name, inode, out); - LOCK (&file->lock); + LOCK (&inode->lock); { - refcount = --file->refcount; + wb_inode = __wb_inode_ctx_get (this, inode); + if (wb_inode == NULL) { + wb_inode = __wb_inode_create (this, inode); + } } - UNLOCK (&file->lock); + UNLOCK (&inode->lock); - if (!refcount){ - LOCK_DESTROY (&file->lock); - GF_FREE (file); - } +out: + return wb_inode; +} + +void +wb_inode_destroy (wb_inode_t *wb_inode) +{ + GF_VALIDATE_OR_GOTO ("write-behind", wb_inode, out); + + LOCK_DESTROY (&wb_inode->lock); + GF_FREE (wb_inode); out: return; } int32_t +wb_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *dict, struct iatt *postparent) +{ + wb_inode_t *wb_inode = NULL; + + if (op_ret < 0) { + goto unwind; + } + + wb_inode = wb_inode_create (this, inode); + if (wb_inode == NULL) { + op_ret = -1; + op_errno = ENOMEM; + } + +unwind: + STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, + dict, postparent); + + return 0; +} + + +int32_t +wb_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) +{ + STACK_WIND (frame, wb_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + return 0; +} + + +int32_t wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { wb_local_t *local = NULL; list_head_t *winds = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; wb_request_t *request = NULL, *dummy = NULL; wb_local_t *per_request_local = NULL; int32_t ret = -1; @@ -432,10 +579,12 @@ wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, local = frame->local; winds = &local->winds; - file = local->file; - GF_VALIDATE_OR_GOTO (this->name, file, out); + fd = local->fd; + + wb_inode = wb_inode_ctx_get (this, fd->inode); + GF_VALIDATE_OR_GOTO (this->name, wb_inode, out); - LOCK (&file->lock); + LOCK (&wb_inode->lock); { list_for_each_entry_safe (request, dummy, winds, winds) { request->flags.write_request.got_reply = 1; @@ -448,7 +597,7 @@ wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, } if (request->flags.write_request.write_behind) { - file->window_current -= request->write_size; + wb_inode->window_current -= request->write_size; total_write_size += request->write_size; } @@ -456,8 +605,8 @@ wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, } if (op_ret == -1) { - file->op_ret = op_ret; - file->op_errno = op_errno; + wb_inode->op_ret = op_ret; + wb_inode->op_errno = op_errno; } else if (op_ret < total_write_size) { /* * We've encountered a short write, for whatever reason. @@ -467,23 +616,21 @@ wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, * TODO: Retry the write so we can potentially capture * a real error condition (i.e., ENOSPC). */ - file->op_ret = -1; - file->op_errno = EIO; + wb_inode->op_ret = -1; + wb_inode->op_errno = EIO; } - - fd = file->fd; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { if (errno == ENOMEM) { - LOCK (&file->lock); + LOCK (&wb_inode->lock); { - file->op_ret = -1; - file->op_errno = ENOMEM; + wb_inode->op_ret = -1; + wb_inode->op_errno = ENOMEM; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } gf_log (this->name, GF_LOG_WARNING, @@ -493,6 +640,12 @@ wb_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, /* safe place to do fd_unref */ fd_unref (fd); + frame->local = NULL; + + if (local != NULL) { + mem_put (frame->local); + } + STACK_DESTROY (frame->root); out: @@ -501,7 +654,7 @@ out: ssize_t -wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds) +wb_sync (call_frame_t *frame, wb_inode_t *wb_inode, list_head_t *winds) { wb_request_t *dummy = NULL, *request = NULL; wb_request_t *first_request = NULL, *next = NULL; @@ -519,15 +672,15 @@ wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds) off_t next_offset_expected = 0; gf_lkowner_t lk_owner = {0, }; - GF_VALIDATE_OR_GOTO_WITH_ERROR ((file ? file->this->name + GF_VALIDATE_OR_GOTO_WITH_ERROR ((wb_inode ? wb_inode->this->name : "write-behind"), frame, out, bytes, -1); - GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, file, out, bytes, + GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, wb_inode, out, bytes, -1); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, winds, out, bytes, -1); - conf = file->this->private; + conf = wb_inode->this->private; list_for_each_entry (request, winds, winds) { total_count += request->stub->args.writev.count; if (total_count > 0) { @@ -536,8 +689,8 @@ wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds) } if (total_count == 0) { - gf_log (file->this->name, GF_LOG_TRACE, "no vectors are to be" - "synced"); + gf_log (wb_inode->this->name, GF_LOG_TRACE, + "no vectors are to be synced"); goto out; } @@ -604,7 +757,10 @@ wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds) || ((current_size + next->write_size) > conf->aggregate_size) || (next_offset_expected != next->stub->args.writev.off) - || (!is_same_lkowner (&lk_owner, &next->lk_owner))) { + || (!is_same_lkowner (&lk_owner, &next->lk_owner)) + || (request->stub->args.writev.fd + != next->stub->args.writev.fd)) { + sync_frame = copy_frame (frame); if (sync_frame == NULL) { bytes = -1; @@ -615,15 +771,8 @@ wb_sync (call_frame_t *frame, wb_file_t *file, list_head_t *winds) frame->root->lk_owner = lk_owner; sync_frame->local = local; - local->file = file; - LOCK (&file->lock); - { - fd = file->fd; - } - UNLOCK (&file->lock); - - fd_ref (fd); + local->fd = fd = fd_ref (request->stub->args.writev.fd); bytes += current_size; STACK_WIND (sync_frame, wb_sync_cbk, @@ -682,13 +831,13 @@ out: } } - if (file != NULL) { - LOCK (&file->lock); + if (wb_inode != NULL) { + LOCK (&wb_inode->lock); { - file->op_ret = -1; - file->op_errno = op_errno; + wb_inode->op_ret = -1; + wb_inode->op_errno = op_errno; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } } @@ -703,15 +852,14 @@ wb_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, wb_local_t *local = NULL; wb_request_t *request = NULL; call_frame_t *process_frame = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; int32_t ret = -1; - fd_t *fd = NULL; GF_ASSERT (frame); GF_ASSERT (this); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; if (request) { @@ -729,15 +877,15 @@ wb_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, } if (process_frame != NULL) { - ret = wb_process_queue (process_frame, file); + ret = wb_process_queue (process_frame, wb_inode); if (ret == -1) { - if ((errno == ENOMEM) && (file != NULL)) { - LOCK (&file->lock); + if ((errno == ENOMEM) && (wb_inode != NULL)) { + LOCK (&wb_inode->lock); { - file->op_ret = -1; - file->op_errno = ENOMEM; + wb_inode->op_ret = -1; + wb_inode->op_errno = ENOMEM; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } gf_log (this->name, GF_LOG_WARNING, @@ -747,16 +895,6 @@ wb_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, STACK_DESTROY (process_frame->root); } - if (file) { - LOCK (&file->lock); - { - fd = file->fd; - } - UNLOCK (&file->lock); - - fd_unref (fd); - } - return 0; } @@ -776,29 +914,18 @@ wb_stat_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) int32_t wb_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - wb_file_t *file = NULL; - fd_t *iter_fd = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1, op_errno = EINVAL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1, op_errno = EINVAL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, loc, unwind); if (loc->inode) { - /* FIXME: fd_lookup extends life of fd till stat returns */ - iter_fd = fd_lookup (loc->inode, frame->root->pid); - if (iter_fd) { - if (!fd_ctx_get (iter_fd, this, &tmp_file)) { - file = (wb_file_t *)(long)tmp_file; - } else { - fd_unref (iter_fd); - iter_fd = NULL; - } - } + wb_inode = wb_inode_ctx_get (this, loc->inode); } local = mem_get0 (this->local_pool); @@ -807,24 +934,24 @@ wb_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; - if (file) { + if (wb_inode) { stub = fop_stat_stub (frame, wb_stat_helper, loc, xdata); if (stub == NULL) { op_errno = ENOMEM; goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -842,10 +969,6 @@ unwind: call_stub_destroy (stub); } - if (iter_fd != NULL) { - fd_unref (iter_fd); - } - return 0; } @@ -854,20 +977,20 @@ int32_t wb_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { - wb_local_t *local = NULL; - wb_request_t *request = NULL; - wb_file_t *file = NULL; - int32_t ret = -1; + wb_local_t *local = NULL; + wb_request_t *request = NULL; + wb_inode_t *wb_inode = NULL; + int32_t ret = -1; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; - if ((file != NULL) && (request != NULL)) { + if ((wb_inode != NULL) && (request != NULL)) { wb_request_unref (request); - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { if (errno == ENOMEM) { op_ret = -1; @@ -900,30 +1023,23 @@ wb_fstat_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) int32_t wb_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - wb_file_t *file = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1; - int op_errno = EINVAL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1; + int op_errno = EINVAL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, fd, unwind); - - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type)) && (wb_inode == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "wb_inode not found for fd %p", fd); + op_errno = EBADFD; + goto unwind; } local = mem_get0 (this->local_pool); @@ -932,18 +1048,18 @@ wb_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; - if (file) { + if (wb_inode) { stub = fop_fstat_stub (frame, wb_fstat_helper, fd, xdata); if (stub == NULL) { op_errno = ENOMEM; goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; @@ -952,7 +1068,7 @@ wb_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) /* FIXME:should the request queue be emptied in case of error? */ - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -982,18 +1098,17 @@ wb_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, { wb_local_t *local = NULL; wb_request_t *request = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; call_frame_t *process_frame = NULL; int32_t ret = -1; - fd_t *fd = NULL; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; - if ((request != NULL) && (file != NULL)) { + if ((request != NULL) && (wb_inode != NULL)) { process_frame = copy_frame (frame); if (process_frame == NULL) { op_ret = -1; @@ -1009,15 +1124,15 @@ wb_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (process_frame != NULL) { - ret = wb_process_queue (process_frame, file); + ret = wb_process_queue (process_frame, wb_inode); if (ret == -1) { - if ((errno == ENOMEM) && (file != NULL)) { - LOCK (&file->lock); + if ((errno == ENOMEM) && (wb_inode != NULL)) { + LOCK (&wb_inode->lock); { - file->op_ret = -1; - file->op_errno = ENOMEM; + wb_inode->op_ret = -1; + wb_inode->op_errno = ENOMEM; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } gf_log (this->name, GF_LOG_WARNING, @@ -1027,16 +1142,6 @@ wb_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, STACK_DESTROY (process_frame->root); } - if (file) { - LOCK (&file->lock); - { - fd = file->fd; - } - UNLOCK (&file->lock); - - fd_unref (fd); - } - return 0; } @@ -1059,31 +1164,18 @@ int32_t wb_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { - wb_file_t *file = NULL; - fd_t *iter_fd = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1, op_errno = EINVAL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1, op_errno = EINVAL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, loc, unwind); if (loc->inode) { - /* - FIXME: fd_lookup extends life of fd till the execution of - truncate_cbk - */ - iter_fd = fd_lookup (loc->inode, frame->root->pid); - if (iter_fd) { - if (!fd_ctx_get (iter_fd, this, &tmp_file)){ - file = (wb_file_t *)(long)tmp_file; - } else { - fd_unref (iter_fd); - } - } + wb_inode = wb_inode_ctx_get (this, loc->inode); } local = mem_get0 (this->local_pool); @@ -1092,10 +1184,10 @@ wb_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; - if (file) { + if (wb_inode) { stub = fop_truncate_stub (frame, wb_truncate_helper, loc, offset, xdata); if (stub == NULL) { @@ -1103,13 +1195,13 @@ wb_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -1138,20 +1230,20 @@ wb_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - wb_local_t *local = NULL; - wb_request_t *request = NULL; - wb_file_t *file = NULL; - int32_t ret = -1; + wb_local_t *local = NULL; + wb_request_t *request = NULL; + wb_inode_t *wb_inode = NULL; + int32_t ret = -1; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; - if ((request != NULL) && (file != NULL)) { + if ((request != NULL) && (wb_inode != NULL)) { wb_request_unref (request); - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { if (errno == ENOMEM) { op_ret = -1; @@ -1187,30 +1279,23 @@ int32_t wb_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { - wb_file_t *file = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1; - int op_errno = EINVAL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1; + int op_errno = EINVAL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, fd, unwind); - - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type)) && (wb_inode == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "wb_inode not found for fd %p", fd); + op_errno = EBADFD; + goto unwind; } local = mem_get0 (this->local_pool); @@ -1219,11 +1304,11 @@ wb_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; - if (file) { + if (wb_inode) { stub = fop_ftruncate_stub (frame, wb_ftruncate_helper, fd, offset, xdata); if (stub == NULL) { @@ -1231,13 +1316,13 @@ wb_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -1268,14 +1353,13 @@ wb_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, wb_local_t *local = NULL; wb_request_t *request = NULL; call_frame_t *process_frame = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; int32_t ret = -1; - fd_t *fd = NULL; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; if (request) { @@ -1294,15 +1378,15 @@ wb_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (request && (process_frame != NULL)) { - ret = wb_process_queue (process_frame, file); + ret = wb_process_queue (process_frame, wb_inode); if (ret == -1) { - if ((errno == ENOMEM) && (file != NULL)) { - LOCK (&file->lock); + if ((errno == ENOMEM) && (wb_inode != NULL)) { + LOCK (&wb_inode->lock); { - file->op_ret = -1; - file->op_errno = ENOMEM; + wb_inode->op_ret = -1; + wb_inode->op_errno = ENOMEM; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } gf_log (this->name, GF_LOG_WARNING, @@ -1312,16 +1396,6 @@ wb_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, STACK_DESTROY (process_frame->root); } - if (file) { - LOCK (&file->lock); - { - fd = file->fd; - } - UNLOCK (&file->lock); - - fd_unref (fd); - } - return 0; } @@ -1343,13 +1417,11 @@ int32_t wb_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - wb_file_t *file = NULL; - fd_t *iter_fd = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1, op_errno = EINVAL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1, op_errno = EINVAL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); @@ -1364,24 +1436,12 @@ wb_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, frame->local = local; if (loc->inode) { - /* - FIXME: fd_lookup extends life of fd till the execution - of wb_utimens_cbk - */ - iter_fd = fd_lookup (loc->inode, frame->root->pid); - if (iter_fd) { - if (!fd_ctx_get (iter_fd, this, &tmp_file)) { - file = (wb_file_t *)(long)tmp_file; - } else { - fd_unref (iter_fd); - } - } - + wb_inode = wb_inode_ctx_get (this, loc->inode); } - local->file = file; + local->wb_inode = wb_inode; - if (file) { + if (wb_inode) { stub = fop_setattr_stub (frame, wb_setattr_helper, loc, stbuf, valid, xdata); if (stub == NULL) { @@ -1389,13 +1449,13 @@ wb_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -1420,23 +1480,29 @@ unwind: void wb_disable_all (xlator_t *this, fd_t *origfd) { - inode_t *inode = NULL; - fd_t *otherfd = NULL; - uint64_t tmp_file = 0; + inode_t *inode = NULL; + fd_t *otherfd = NULL; + wb_file_t *wb_file = NULL; inode = origfd->inode; + LOCK(&inode->lock); - list_for_each_entry (otherfd, &inode->fd_list, inode_list) { - if (otherfd == origfd) { - continue; - } - if (fd_ctx_get(otherfd,this,&tmp_file)) { - continue; + { + list_for_each_entry (otherfd, &inode->fd_list, inode_list) { + if (otherfd == origfd) { + continue; + } + + wb_file = wb_fd_ctx_get (this, otherfd); + if (wb_file == NULL) { + continue; + } + + gf_log(this->name,GF_LOG_DEBUG, + "disabling wb on %p because %p is O_SYNC", + otherfd, origfd); + wb_file->disabled = 1; } - gf_log(this->name,GF_LOG_DEBUG, - "disabling wb on %p because %p is O_SYNC", - otherfd, origfd); - ((wb_file_t *)(long)tmp_file)->disabled = 1; } UNLOCK(&inode->lock); } @@ -1447,15 +1513,11 @@ wb_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, { int32_t flags = 0; wb_file_t *file = NULL; - wb_conf_t *conf = NULL; wb_local_t *local = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, this, out, op_errno, EINVAL); - - conf = this->private; - local = frame->local; GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, op_errno, EINVAL); @@ -1469,30 +1531,14 @@ wb_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, op_errno = ENOMEM; goto out; } - - LOCK (&file->lock); - { - /* If O_DIRECT then, we disable caching */ - if (((flags & O_DIRECT) == O_DIRECT) - || ((flags & O_ACCMODE) == O_RDONLY) - || (((flags & O_SYNC) == O_SYNC) - && conf->enable_O_SYNC == _gf_true)) { - gf_log(this->name,GF_LOG_DEBUG, - "disabling wb on %p", fd); - file->disabled = 1; - wb_disable_all(this,fd); - } - /* TODO: decide about wbflags's fate */ - /* - else if (wbflags & GF_OPEN_NOWB) { - file->disabled = 1; - } - */ - } - UNLOCK (&file->lock); } out: + frame->local = NULL; + if (local != NULL) { + mem_put (local); + } + STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata); return 0; } @@ -1531,15 +1577,15 @@ wb_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *buf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { - long flags = 0; - wb_file_t *file = NULL; - wb_conf_t *conf = NULL; + long flags = 0; + wb_inode_t *wb_inode = NULL; + wb_file_t *file = NULL; + wb_local_t *local = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, this, out, op_errno, EINVAL); - conf = this->private; if (op_ret != -1) { if (frame->local) { flags = (long) frame->local; @@ -1552,19 +1598,15 @@ wb_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - LOCK (&file->lock); + LOCK (&inode->lock); { - /* If O_DIRECT then, we disable caching */ - if (frame->local) { - if (((flags & O_DIRECT) == O_DIRECT) - || ((flags & O_ACCMODE) == O_RDONLY) - || (((flags & O_SYNC) == O_SYNC) - && (conf->enable_O_SYNC == _gf_true))) { - file->window_conf = 0; - } + wb_inode = __wb_inode_create (this, inode); + if (wb_inode == NULL) { + op_ret = -1; + op_errno = ENOMEM; } } - UNLOCK (&file->lock); + UNLOCK (&inode->lock); } frame->local = NULL; @@ -1572,6 +1614,11 @@ wb_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf, preparent, postparent, xdata); + + if (local != NULL) { + mem_put (local); + } + return 0; } @@ -1580,14 +1627,23 @@ int32_t wb_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { - int32_t op_errno = EINVAL; + int32_t op_errno = EINVAL; + wb_local_t *local = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, fd, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, loc, unwind); - frame->local = (void *)(long)flags; + local = mem_get0 (this->local_pool); + if (local == NULL) { + op_errno = ENOMEM; + goto unwind; + } + + local->flags = flags; + + frame->local = local; STACK_WIND (frame, wb_create_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, @@ -1607,19 +1663,22 @@ unwind: * will fit into a single write call to server. */ size_t -__wb_mark_wind_all (wb_file_t *file, list_head_t *list, list_head_t *winds) +__wb_mark_wind_all (wb_inode_t *wb_inode, list_head_t *list, list_head_t *winds) { - wb_request_t *request = NULL; - size_t size = 0; - char first_request = 1, overlap = 0; - wb_conf_t *conf = NULL; - int count = 0; + wb_request_t *request = NULL, *prev_request = NULL; + wb_file_t *wb_file = NULL, *prev_wb_file = NULL; + wb_file_t *last_wb_file = NULL; + size_t size = 0; + char first_request = 1, overlap = 0; + wb_conf_t *conf = NULL; + int count = 0; + enum _gf_boolean dont_wind_set = 0; - GF_VALIDATE_OR_GOTO ("write-behind", file, out); - GF_VALIDATE_OR_GOTO (file->this->name, list, out); - GF_VALIDATE_OR_GOTO (file->this->name, winds, out); + GF_VALIDATE_OR_GOTO ("write-behind", wb_inode, out); + GF_VALIDATE_OR_GOTO (wb_inode->this->name, list, out); + GF_VALIDATE_OR_GOTO (wb_inode->this->name, winds, out); - conf = file->this->private; + conf = wb_inode->this->private; list_for_each_entry (request, list, list) { @@ -1628,25 +1687,60 @@ __wb_mark_wind_all (wb_file_t *file, list_head_t *list, list_head_t *winds) break; } + wb_file = wb_fd_ctx_get (wb_inode->this, + request->stub->args.writev.fd); + if (wb_file == NULL) { + gf_log (wb_inode->this->name, GF_LOG_WARNING, + "write behind wb_file pointer is" + " not stored in context of fd(%p)", + request->stub->args.writev.fd); + goto out; + } + + /* If write requests from two fds are interleaved, for + * each of them, we can only send first set of adjacent + * requests that are on same fd. This is because, fds + * with O_APPEND cannot have more than one write fop in + * progress while syncing, so that order is not messed + * up. Since we group adjacent requests with same fd into + * single write call whenever possible, we need the above said + * measure. + */ + if ((prev_wb_file != NULL) && (prev_wb_file->flags & O_APPEND) + && (prev_request->stub->args.writev.fd + != request->stub->args.writev.fd) + && (!prev_wb_file->dont_wind)) { + prev_wb_file->dont_wind = 1; + dont_wind_set = 1; + last_wb_file = prev_wb_file; + } + + prev_request = request; + prev_wb_file = wb_file; + if (!request->flags.write_request.stack_wound) { if (first_request) { first_request = 0; } else { overlap = wb_overlap (list, request); if (overlap) { - goto out; + continue; } } - if ((file->flags & O_APPEND) + if ((wb_file->flags & O_APPEND) && (((size + request->write_size) > conf->aggregate_size) || ((count + request->stub->args.writev.count) - > MAX_VECTOR_COUNT))) { - goto out; + > MAX_VECTOR_COUNT) + || (wb_file->dont_wind))) { + continue; } size += request->write_size; + + wb_inode->aggregate_current -= request->write_size; + count += request->stub->args.writev.count; request->flags.write_request.stack_wound = 1; @@ -1655,8 +1749,22 @@ __wb_mark_wind_all (wb_file_t *file, list_head_t *list, list_head_t *winds) } out: - if (file != NULL) { - file->aggregate_current -= size; + if (wb_inode != NULL) { + wb_inode->aggregate_current -= size; + } + + if (dont_wind_set && (list != NULL)) { + list_for_each_entry (request, list, list) { + wb_file = wb_fd_ctx_get (wb_inode->this, + request->stub->args.writev.fd); + if (wb_file != NULL) { + wb_file->dont_wind = 0; + } + + if (wb_file == last_wb_file) { + break; + } + } } return size; @@ -1729,7 +1837,7 @@ __wb_mark_winds (list_head_t *list, list_head_t *winds, size_t aggregate_conf, char incomplete_writes = 0; char overlapping_writes = 0; wb_request_t *request = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; char wind_all = 0; int32_t ret = 0; @@ -1741,13 +1849,13 @@ __wb_mark_winds (list_head_t *list, list_head_t *winds, size_t aggregate_conf, } request = list_entry (list->next, typeof (*request), list); - file = request->file; + wb_inode = request->wb_inode; ret = __wb_can_wind (list, &other_fop_in_queue, &overlapping_writes, &incomplete_writes, &wind_all); if (ret == -1) { - gf_log (file->this->name, GF_LOG_WARNING, + gf_log (wb_inode->this->name, GF_LOG_WARNING, "cannot decide whether to wind or not"); goto out; } @@ -1755,9 +1863,9 @@ __wb_mark_winds (list_head_t *list, list_head_t *winds, size_t aggregate_conf, if (!incomplete_writes && ((enable_trickling_writes) || (wind_all) || (overlapping_writes) || (other_fop_in_queue) - || (file->aggregate_current + || (wb_inode->aggregate_current >= aggregate_conf))) { - size = __wb_mark_wind_all (file, list, winds); + size = __wb_mark_wind_all (wb_inode, list, winds); } out: @@ -1770,14 +1878,14 @@ __wb_mark_unwind_till (list_head_t *list, list_head_t *unwinds, size_t size) { size_t written_behind = 0; wb_request_t *request = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; if (list_empty (list)) { goto out; } request = list_entry (list->next, typeof (*request), list); - file = request->file; + wb_inode = request->wb_inode; list_for_each_entry (request, list, list) { @@ -1793,7 +1901,7 @@ __wb_mark_unwind_till (list_head_t *list, list_head_t *unwinds, size_t size) list_add_tail (&request->unwinds, unwinds); if (!request->flags.write_request.got_reply) { - file->window_current + wb_inode->window_current += request->write_size; } } @@ -1810,8 +1918,8 @@ out: void __wb_mark_unwinds (list_head_t *list, list_head_t *unwinds) { - wb_request_t *request = NULL; - wb_file_t *file = NULL; + wb_request_t *request = NULL; + wb_inode_t *wb_inode = NULL; GF_VALIDATE_OR_GOTO ("write-behind", list, out); GF_VALIDATE_OR_GOTO ("write-behind", unwinds, out); @@ -1821,12 +1929,12 @@ __wb_mark_unwinds (list_head_t *list, list_head_t *unwinds) } request = list_entry (list->next, typeof (*request), list); - file = request->file; + wb_inode = request->wb_inode; - if (file->window_current <= file->window_conf) { + if (wb_inode->window_current <= wb_inode->window_conf) { __wb_mark_unwind_till (list, unwinds, - file->window_conf - - file->window_current); + wb_inode->window_conf + - wb_inode->window_current); } out: @@ -1892,7 +2000,7 @@ out: int32_t -wb_resume_other_requests (call_frame_t *frame, wb_file_t *file, +wb_resume_other_requests (call_frame_t *frame, wb_inode_t *wb_inode, list_head_t *other_requests) { int32_t ret = -1; @@ -1901,9 +2009,9 @@ wb_resume_other_requests (call_frame_t *frame, wb_file_t *file, char wind = 0; call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ((file ? file->this->name : "write-behind"), frame, - out); - GF_VALIDATE_OR_GOTO (frame->this->name, file, out); + GF_VALIDATE_OR_GOTO ((wb_inode ? wb_inode->this->name : "write-behind"), + frame, out); + GF_VALIDATE_OR_GOTO (frame->this->name, wb_inode, out); GF_VALIDATE_OR_GOTO (frame->this->name, other_requests, out); if (list_empty (other_requests)) { @@ -1916,11 +2024,11 @@ wb_resume_other_requests (call_frame_t *frame, wb_file_t *file, wind = request->stub->wind; stub = request->stub; - LOCK (&file->lock); + LOCK (&wb_inode->lock); { request->stub = NULL; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); if (!wind) { wb_request_unref (request); @@ -1933,7 +2041,7 @@ wb_resume_other_requests (call_frame_t *frame, wb_file_t *file, ret = 0; if (fops_removed > 0) { - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (frame->this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -1946,26 +2054,26 @@ out: int32_t -wb_do_ops (call_frame_t *frame, wb_file_t *file, list_head_t *winds, +wb_do_ops (call_frame_t *frame, wb_inode_t *wb_inode, list_head_t *winds, list_head_t *unwinds, list_head_t *other_requests) { int32_t ret = -1, write_requests_removed = 0; - GF_VALIDATE_OR_GOTO ((file ? file->this->name : "write-behind"), + GF_VALIDATE_OR_GOTO ((wb_inode ? wb_inode->this->name : "write-behind"), frame, out); - GF_VALIDATE_OR_GOTO (frame->this->name, file, out); + GF_VALIDATE_OR_GOTO (frame->this->name, wb_inode, out); ret = wb_stack_unwind (unwinds); write_requests_removed = ret; - ret = wb_sync (frame, file, winds); + ret = wb_sync (frame, wb_inode, winds); if (ret == -1) { gf_log (frame->this->name, GF_LOG_WARNING, "syncing of write requests failed"); } - ret = wb_resume_other_requests (frame, file, other_requests); + ret = wb_resume_other_requests (frame, wb_inode, other_requests); if (ret == -1) { gf_log (frame->this->name, GF_LOG_WARNING, "cannot resume non-write requests in request queue"); @@ -1977,7 +2085,7 @@ wb_do_ops (call_frame_t *frame, wb_file_t *file, list_head_t *winds, * blocked on the writes just unwound. */ if (write_requests_removed > 0) { - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (frame->this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -1999,7 +2107,7 @@ __wb_copy_into_holder (wb_request_t *holder, wb_request_t *request) if (holder->flags.write_request.virgin) { /* TODO: check the required size */ - iobuf = iobuf_get (request->file->this->ctx->iobuf_pool); + iobuf = iobuf_get (request->wb_inode->this->ctx->iobuf_pool); if (iobuf == NULL) { goto out; } @@ -2014,7 +2122,7 @@ __wb_copy_into_holder (wb_request_t *holder, wb_request_t *request) if (ret != 0) { iobuf_unref (iobuf); iobref_unref (iobref); - gf_log (request->file->this->name, GF_LOG_WARNING, + gf_log (request->wb_inode->this->name, GF_LOG_WARNING, "cannot add iobuf (%p) into iobref (%p)", iobuf, iobref); goto out; @@ -2041,7 +2149,7 @@ __wb_copy_into_holder (wb_request_t *holder, wb_request_t *request) holder->write_size += request->write_size; request->flags.write_request.stack_wound = 1; - list_move_tail (&request->list, &request->file->passive_requests); + list_move_tail (&request->list, &request->wb_inode->passive_requests); ret = 0; out: @@ -2079,7 +2187,9 @@ __wb_collapse_write_bufs (list_head_t *requests, size_t page_size) if ((request->stub->args.writev.off != offset_expected) || (!is_same_lkowner (&request->lk_owner, - &holder->lk_owner))) { + &holder->lk_owner)) + || (holder->stub->args.writev.fd + != request->stub->args.writev.fd)) { holder = request; continue; } @@ -2107,7 +2217,7 @@ out: int32_t -wb_process_queue (call_frame_t *frame, wb_file_t *file) +wb_process_queue (call_frame_t *frame, wb_inode_t *wb_inode) { list_head_t winds = {0, }, unwinds = {0, }, other_requests = {0, }; size_t size = 0; @@ -2119,15 +2229,15 @@ wb_process_queue (call_frame_t *frame, wb_file_t *file) INIT_LIST_HEAD (&unwinds); INIT_LIST_HEAD (&other_requests); - GF_VALIDATE_OR_GOTO ((file ? file->this->name : "write-behind"), frame, - out); - GF_VALIDATE_OR_GOTO (file->this->name, frame, out); + GF_VALIDATE_OR_GOTO ((wb_inode ? wb_inode->this->name : "write-behind"), + frame, out); + GF_VALIDATE_OR_GOTO (wb_inode->this->name, frame, out); - conf = file->this->private; - GF_VALIDATE_OR_GOTO (file->this->name, conf, out); + conf = wb_inode->this->private; + GF_VALIDATE_OR_GOTO (wb_inode->this->name, conf, out); size = conf->aggregate_size; - LOCK (&file->lock); + LOCK (&wb_inode->lock); { /* * make sure requests are marked for unwinding and adjacent @@ -2135,23 +2245,23 @@ wb_process_queue (call_frame_t *frame, wb_file_t *file) * an iobuf) are packed properly so that iobufs are filled to * their maximum capacity, before calling __wb_mark_winds. */ - __wb_mark_unwinds (&file->request, &unwinds); + __wb_mark_unwinds (&wb_inode->request, &unwinds); - __wb_collapse_write_bufs (&file->request, - file->this->ctx->page_size); + __wb_collapse_write_bufs (&wb_inode->request, + wb_inode->this->ctx->page_size); - count = __wb_get_other_requests (&file->request, + count = __wb_get_other_requests (&wb_inode->request, &other_requests); if (count == 0) { - __wb_mark_winds (&file->request, &winds, size, + __wb_mark_winds (&wb_inode->request, &winds, size, conf->enable_trickling_writes); } } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); - ret = wb_do_ops (frame, file, &winds, &unwinds, &other_requests); + ret = wb_do_ops (frame, wb_inode, &winds, &unwinds, &other_requests); out: return ret; @@ -2176,15 +2286,15 @@ wb_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t offset, uint32_t flags, struct iobref *iobref, dict_t *xdata) { - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; + wb_file_t *wb_file = NULL; char wb_disabled = 0; call_frame_t *process_frame = NULL; - size_t size = 0; - uint64_t tmp_file = 0; call_stub_t *stub = NULL; wb_local_t *local = NULL; wb_request_t *request = NULL; int32_t ret = -1; + size_t size = 0; int32_t op_ret = -1, op_errno = EINVAL; GF_ASSERT (frame); @@ -2194,49 +2304,44 @@ wb_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, fd, unwind, op_errno, EINVAL); - if (vector != NULL) + if (vector != NULL) { size = iov_length (vector, count); - - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } } - if (file != NULL) { - LOCK (&file->lock); - { - op_ret = file->op_ret; - op_errno = file->op_errno; - - file->op_ret = 0; + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type)) && (wb_inode == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "write behind wb_inode pointer is" + " not stored in context of inode(%p), returning EBADFD", + fd->inode); + op_errno = EBADFD; + goto unwind; + } - if ((op_ret == 0) - && (file->disabled || file->disable_till)) { - if (size > file->disable_till) { - file->disable_till = 0; - } else { - file->disable_till -= size; - } - wb_disabled = 1; + if (wb_file != NULL) { + if (wb_file->disabled || wb_file->disable_till) { + if (size > wb_file->disable_till) { + wb_file->disable_till = 0; + } else { + wb_file->disable_till -= size; } + wb_disabled = 1; } - UNLOCK (&file->lock); } else { wb_disabled = 1; } + if (wb_inode != NULL) { + LOCK (&wb_inode->lock); + { + op_ret = wb_inode->op_ret; + op_errno = wb_inode->op_errno; + } + UNLOCK (&wb_inode->lock); + } + if (op_ret == -1) { - STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, NULL, - NULL, NULL); - return 0; + goto unwind; } if (wb_disabled) { @@ -2259,7 +2364,7 @@ wb_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, } frame->local = local; - local->file = file; + local->wb_inode = wb_inode; stub = fop_writev_stub (frame, NULL, fd, vector, count, offset, flags, iobref, xdata); @@ -2268,13 +2373,13 @@ wb_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (process_frame, file); + ret = wb_process_queue (process_frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -2285,6 +2390,10 @@ wb_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, return 0; unwind: + local = frame->local; + frame->local = NULL; + mem_put (local); + STACK_UNWIND_STRICT (writev, frame, -1, op_errno, NULL, NULL, NULL); if (process_frame) { @@ -2304,21 +2413,21 @@ wb_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iovec *vector, int32_t count, struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) { - wb_local_t *local = NULL; - wb_file_t *file = NULL; - wb_request_t *request = NULL; - int32_t ret = 0; + wb_local_t *local = NULL; + wb_inode_t *wb_inode = NULL; + wb_request_t *request = NULL; + int32_t ret = 0; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; - if ((request != NULL) && (file != NULL)) { + if ((request != NULL) && (wb_inode != NULL)) { wb_request_unref (request); - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { if (errno == ENOMEM) { op_ret = -1; @@ -2353,12 +2462,11 @@ int32_t wb_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { - wb_file_t *file = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - int32_t ret = -1, op_errno = 0; - wb_request_t *request = NULL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + int32_t ret = -1, op_errno = 0; + wb_request_t *request = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, this, unwind, @@ -2366,17 +2474,14 @@ wb_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, fd, unwind, op_errno, EINVAL); - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type)) && (wb_inode == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "write behind wb_inode pointer is" + " not stored in context of inode(%p), returning " + "EBADFD", fd->inode); + op_errno = EBADFD; + goto unwind; } local = mem_get0 (this->local_pool); @@ -2385,10 +2490,10 @@ wb_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; - if (file) { + if (wb_inode) { stub = fop_readv_stub (frame, wb_readv_helper, fd, size, offset, flags, xdata); if (stub == NULL) { @@ -2396,14 +2501,14 @@ wb_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { call_stub_destroy (stub); op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -2436,25 +2541,25 @@ int32_t wb_ffr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { - wb_local_t *local = NULL; - wb_file_t *file = NULL; + wb_local_t *local = NULL; + wb_inode_t *wb_inode = NULL; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; - if (file != NULL) { - LOCK (&file->lock); + if (wb_inode != NULL) { + LOCK (&wb_inode->lock); { - if (file->op_ret == -1) { - op_ret = file->op_ret; - op_errno = file->op_errno; + if (wb_inode->op_ret == -1) { + op_ret = wb_inode->op_ret; + op_errno = wb_inode->op_errno; - file->op_ret = 0; + wb_inode->op_ret = 0; } } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); } STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, xdata); @@ -2468,7 +2573,7 @@ wb_flush_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { wb_conf_t *conf = NULL; wb_local_t *local = NULL; - wb_file_t *file = NULL; + wb_inode_t *wb_inode = NULL; call_frame_t *flush_frame = NULL, *process_frame = NULL; int32_t op_ret = -1, op_errno = -1, ret = -1; @@ -2479,14 +2584,14 @@ wb_flush_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) conf = this->private; local = frame->local; - file = local->file; + wb_inode = local->wb_inode; - LOCK (&file->lock); + LOCK (&wb_inode->lock); { - op_ret = file->op_ret; - op_errno = file->op_errno; + op_ret = wb_inode->op_ret; + op_errno = wb_inode->op_errno; } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); if (local && local->request) { process_frame = copy_frame (frame); @@ -2513,7 +2618,7 @@ wb_flush_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) } if (process_frame != NULL) { - ret = wb_process_queue (process_frame, file); + ret = wb_process_queue (process_frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -2537,14 +2642,13 @@ unwind: int32_t wb_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - wb_conf_t *conf = NULL; - wb_file_t *file = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - call_frame_t *flush_frame = NULL; - wb_request_t *request = NULL; - int32_t ret = 0, op_errno = 0; + wb_conf_t *conf = NULL; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + call_frame_t *flush_frame = NULL; + wb_request_t *request = NULL; + int32_t ret = 0, op_errno = 0; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, this, unwind, @@ -2554,28 +2658,24 @@ wb_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) conf = this->private; - - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type)) && (wb_inode == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "write behind wb_inode pointer is" + " not stored in context of inode(%p), " + "returning EBADFD", fd->inode); + op_errno = EBADFD; + goto unwind; } - if (file != NULL) { + if (wb_inode != NULL) { local = mem_get0 (this->local_pool); if (local == NULL) { op_errno = ENOMEM; goto unwind; } - local->file = file; + local->wb_inode = wb_inode; frame->local = local; @@ -2585,14 +2685,14 @@ wb_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { call_stub_destroy (stub); op_errno = ENOMEM; goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); @@ -2629,32 +2729,32 @@ wb_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - wb_local_t *local = NULL; - wb_file_t *file = NULL; - wb_request_t *request = NULL; - int32_t ret = -1; + wb_local_t *local = NULL; + wb_inode_t *wb_inode = NULL; + wb_request_t *request = NULL; + int32_t ret = -1; GF_ASSERT (frame); local = frame->local; - file = local->file; + wb_inode = local->wb_inode; request = local->request; - if (file != NULL) { - LOCK (&file->lock); + if (wb_inode != NULL) { + LOCK (&wb_inode->lock); { - if (file->op_ret == -1) { - op_ret = file->op_ret; - op_errno = file->op_errno; + if (wb_inode->op_ret == -1) { + op_ret = wb_inode->op_ret; + op_errno = wb_inode->op_errno; - file->op_ret = 0; + wb_inode->op_ret = 0; } } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); if (request) { wb_request_unref (request); - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { if (errno == ENOMEM) { op_ret = -1; @@ -2689,12 +2789,11 @@ int32_t wb_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, dict_t *xdata) { - wb_file_t *file = NULL; - wb_local_t *local = NULL; - uint64_t tmp_file = 0; - call_stub_t *stub = NULL; - wb_request_t *request = NULL; - int32_t ret = -1, op_errno = 0; + wb_inode_t *wb_inode = NULL; + wb_local_t *local = NULL; + call_stub_t *stub = NULL; + wb_request_t *request = NULL; + int32_t ret = -1, op_errno = 0; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, this, unwind, @@ -2702,18 +2801,14 @@ wb_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, GF_VALIDATE_OR_GOTO_WITH_ERROR (frame->this->name, fd, unwind, op_errno, EINVAL); - - if ((!IA_ISDIR (fd->inode->ia_type)) - && fd_ctx_get (fd, this, &tmp_file)) { - file = wb_file_create (this, fd, 0); - } else { - file = (wb_file_t *)(long)tmp_file; - if ((!IA_ISDIR (fd->inode->ia_type)) && (file == NULL)) { - gf_log (this->name, GF_LOG_WARNING, - "wb_file not found for fd %p", fd); - op_errno = EBADFD; - goto unwind; - } + wb_inode = wb_inode_ctx_get (this, fd->inode); + if ((!IA_ISDIR (fd->inode->ia_type))) { + gf_log (this->name, GF_LOG_WARNING, + "write behind wb_inode pointer is" + " not stored in context of inode(%p), " + "returning EBADFD", fd->inode); + op_errno = EBADFD; + goto unwind; } local = mem_get0 (this->local_pool); @@ -2722,11 +2817,9 @@ wb_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, goto unwind; } - local->file = file; - frame->local = local; - if (file) { + if (wb_inode) { stub = fop_fsync_stub (frame, wb_fsync_helper, fd, datasync, xdata); if (stub == NULL) { @@ -2734,21 +2827,22 @@ wb_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, goto unwind; } - request = wb_enqueue (file, stub); + request = wb_enqueue (wb_inode, stub); if (request == NULL) { op_errno = ENOMEM; call_stub_destroy (stub); goto unwind; } - ret = wb_process_queue (frame, file); + ret = wb_process_queue (frame, wb_inode); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "request queue processing failed"); } } else { STACK_WIND (frame, wb_fsync_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, fd, datasync, xdata); + FIRST_CHILD(this)->fops->fsync, fd, datasync, + xdata); } return 0; @@ -2760,28 +2854,77 @@ unwind: int32_t +wb_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + + if (op_ret <= 0) { + goto unwind; + } + + list_for_each_entry (entry, &entries->list, list) { + if (!entry->inode) + continue; + wb_inode_create (this, entry->inode); + } + +unwind: + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata); + return 0; +} + + +int32_t +wb_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, dict_t *xdata) +{ + STACK_WIND (frame, wb_readdirp_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata); + return 0; +} + + +int32_t wb_release (xlator_t *this, fd_t *fd) { - uint64_t file_ptr = 0; - wb_file_t *file = NULL; + uint64_t wb_file_ptr = 0; + wb_file_t *wb_file = NULL; GF_VALIDATE_OR_GOTO ("write-behind", this, out); GF_VALIDATE_OR_GOTO (this->name, fd, out); - fd_ctx_get (fd, this, &file_ptr); - file = (wb_file_t *) (long) file_ptr; + fd_ctx_del (fd, this, &wb_file_ptr); + wb_file = (wb_file_t *)(long) wb_file_ptr; + + GF_FREE (wb_file); + +out: + return 0; +} + + +int32_t +wb_forget (xlator_t *this, inode_t *inode) +{ + uint64_t tmp = 0; + wb_inode_t *wb_inode = NULL; + + inode_ctx_del (inode, this, &tmp); + + wb_inode = (wb_inode_t *)(long)tmp; - if (file != NULL) { - LOCK (&file->lock); + if (wb_inode != NULL) { + LOCK (&wb_inode->lock); { - GF_ASSERT (list_empty (&file->request)); + GF_ASSERT (list_empty (&wb_inode->request)); } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); - wb_file_destroy (file); + wb_inode_destroy (wb_inode); } -out: return 0; } @@ -2805,7 +2948,6 @@ wb_priv_dump (xlator_t *this) gf_proc_dump_write ("aggregate_size", "%d", conf->aggregate_size); gf_proc_dump_write ("window_size", "%d", conf->window_size); - gf_proc_dump_write ("disable_till", "%d", conf->disable_till); gf_proc_dump_write ("enable_O_SYNC", "%d", conf->enable_O_SYNC); gf_proc_dump_write ("flush_behind", "%d", conf->flush_behind); gf_proc_dump_write ("enable_trickling_writes", "%d", @@ -2866,75 +3008,62 @@ __wb_dump_requests (struct list_head *head, char *prefix, char passive) int -wb_file_dump (xlator_t *this, fd_t *fd) +wb_inode_dump (xlator_t *this, inode_t *inode) { - wb_file_t *file = NULL; - uint64_t tmp_file = 0; - int32_t ret = -1; - char *path = NULL; + wb_inode_t *wb_inode = NULL; + int32_t ret = -1; + char *path = NULL; char key_prefix[GF_DUMP_MAX_BUF_LEN] = {0, }; - if ((fd == NULL) || (this == NULL)) { - ret = 0; - goto out; - } - - ret = fd_ctx_get (fd, this, &tmp_file); - if (ret == -1) { + if ((inode == NULL) || (this == NULL)) { ret = 0; goto out; } - file = (wb_file_t *)(long)tmp_file; - if (file == NULL) { + wb_inode = wb_inode_ctx_get (this, inode); + if (wb_inode == NULL) { ret = 0; goto out; } gf_proc_dump_build_key (key_prefix, "xlator.performance.write-behind", - "file"); + "wb_inode"); gf_proc_dump_add_section (key_prefix); - __inode_path (fd->inode, NULL, &path); + __inode_path (inode, NULL, &path); if (path != NULL) { gf_proc_dump_write ("path", "%s", path); GF_FREE (path); } - gf_proc_dump_write ("fd", "%p", fd); - - gf_proc_dump_write ("disabled", "%d", file->disabled); - - gf_proc_dump_write ("disable_till", "%lu", file->disable_till); + gf_proc_dump_write ("inode", "%p", inode); - gf_proc_dump_write ("window_conf", "%"GF_PRI_SIZET, file->window_conf); + gf_proc_dump_write ("window_conf", "%"GF_PRI_SIZET, + wb_inode->window_conf); - gf_proc_dump_write ("window_current", "%"GF_PRI_SIZET, file->window_current); + gf_proc_dump_write ("window_current", "%"GF_PRI_SIZET, + wb_inode->window_current); - gf_proc_dump_write ("flags", "%s", (file->flags & O_APPEND) ? "O_APPEND" - : "!O_APPEND"); - - gf_proc_dump_write ("aggregate_current", "%"GF_PRI_SIZET, file->aggregate_current); - - gf_proc_dump_write ("refcount", "%d", file->refcount); + gf_proc_dump_write ("aggregate_current", "%"GF_PRI_SIZET, + wb_inode->aggregate_current); - gf_proc_dump_write ("op_ret", "%d", file->op_ret); + gf_proc_dump_write ("op_ret", "%d", wb_inode->op_ret); - gf_proc_dump_write ("op_errno", "%d", file->op_errno); + gf_proc_dump_write ("op_errno", "%d", wb_inode->op_errno); - LOCK (&file->lock); + LOCK (&wb_inode->lock); { - if (!list_empty (&file->request)) { - __wb_dump_requests (&file->request, key_prefix, 0); + if (!list_empty (&wb_inode->request)) { + __wb_dump_requests (&wb_inode->request, key_prefix, 0); } - if (!list_empty (&file->passive_requests)) { - __wb_dump_requests (&file->passive_requests, key_prefix, - 1); + if (!list_empty (&wb_inode->passive_requests)) { + __wb_dump_requests (&wb_inode->passive_requests, + key_prefix, 1); } } - UNLOCK (&file->lock); + UNLOCK (&wb_inode->lock); ret = 0; out: @@ -2942,6 +3071,48 @@ out: } +int +wb_fd_dump (xlator_t *this, fd_t *fd) +{ + wb_file_t *wb_file = NULL; + char *path = NULL; + char key_prefix[GF_DUMP_MAX_BUF_LEN] = {0, }; + + if ((fd == NULL) || (this == NULL)) { + goto out; + } + + wb_file = wb_fd_ctx_get (this, fd); + if (wb_file == NULL) { + goto out; + } + + gf_proc_dump_build_key (key_prefix, "xlator.performance.write-behind", + "wb_file"); + + gf_proc_dump_add_section (key_prefix); + + __inode_path (fd->inode, NULL, &path); + if (path != NULL) { + gf_proc_dump_write ("path", "%s", path); + GF_FREE (path); + } + + gf_proc_dump_write ("fd", "%p", fd); + + gf_proc_dump_write ("flags", "%d", wb_file->flags); + + gf_proc_dump_write ("flags", "%s", + (wb_file->flags & O_APPEND) ? "O_APPEND" + : "!O_APPEND"); + + gf_proc_dump_write ("disabled", "%d", wb_file->disabled); + +out: + return 0; +} + + int32_t mem_acct_init (xlator_t *this) { @@ -2998,7 +3169,7 @@ init (xlator_t *this) if (this->parents == NULL) { gf_log (this->name, GF_LOG_WARNING, - "dangling volume. check volfile"); + "dangling volume. check volfilex"); } conf = GF_CALLOC (1, sizeof (*conf), gf_wb_mt_wb_conf_t); @@ -3011,9 +3182,6 @@ init (xlator_t *this) /* configure 'options aggregate-size <size>' */ conf->aggregate_size = WB_AGGREGATE_SIZE; - GF_OPTION_INIT("disable-for-first-nbytes", conf->disable_till, size, - out); - /* configure 'option window-size <size>' */ GF_OPTION_INIT ("cache-size", conf->window_size, size, out); @@ -3036,8 +3204,8 @@ init (xlator_t *this) /* configure 'option flush-behind <on/off>' */ GF_OPTION_INIT ("flush-behind", conf->flush_behind, bool, out); - GF_OPTION_INIT ("enable-trickling-writes", conf->enable_trickling_writes, - bool, out); + GF_OPTION_INIT ("enable-trickling-writes", + conf->enable_trickling_writes, bool, out); this->local_pool = mem_pool_new (wb_local_t, 64); if (!this->local_pool) { @@ -3079,6 +3247,7 @@ out: struct xlator_fops fops = { + .lookup = wb_lookup, .writev = wb_writev, .open = wb_open, .create = wb_create, @@ -3090,6 +3259,7 @@ struct xlator_fops fops = { .truncate = wb_truncate, .ftruncate = wb_ftruncate, .setattr = wb_setattr, + .readdirp = wb_readdirp, }; struct xlator_cbks cbks = { @@ -3098,7 +3268,8 @@ struct xlator_cbks cbks = { struct xlator_dumpops dumpops = { .priv = wb_priv_dump, - .fdctx = wb_file_dump, + .inodectx = wb_inode_dump, + .fdctx = wb_fd_dump, }; struct volume_options options[] = { @@ -3116,7 +3287,8 @@ struct volume_options options[] = { .min = 512 * GF_UNIT_KB, .max = 1 * GF_UNIT_GB, .default_value = "1MB", - .description = "Size of the per-file write-behind buffer. " + .description = "Size of the write-behind buffer for a single file " + "(inode)." }, { .key = {"disable-for-first-nbytes"}, |