diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | libglusterfs/src/fd.c | 42 | ||||
-rw-r--r-- | libglusterfs/src/fd.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/inode.c | 33 | ||||
-rw-r--r-- | libglusterfs/src/inode.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/xlator.c | 10 | ||||
-rw-r--r-- | transport/ib-verbs/src/ib-verbs.c | 2 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-dir-write.c | 129 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-inode-write.c | 213 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr.c | 57 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr.h | 17 | ||||
-rw-r--r-- | xlators/debug/io-stats/src/io-stats.c | 68 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 322 | ||||
-rwxr-xr-x | xlators/mount/fuse/utils/mount.glusterfs.in | 8 | ||||
-rw-r--r-- | xlators/performance/Makefile.am | 2 | ||||
-rw-r--r-- | xlators/performance/quick-read/Makefile.am | 3 | ||||
-rw-r--r-- | xlators/performance/quick-read/src/Makefile.am | 14 | ||||
-rw-r--r-- | xlators/performance/quick-read/src/quick-read.c | 2235 | ||||
-rw-r--r-- | xlators/performance/quick-read/src/quick-read.h | 78 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-protocol.c | 6 |
20 files changed, 2951 insertions, 292 deletions
diff --git a/configure.ac b/configure.ac index 1d72047ce..630ace3ac 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,8 @@ AC_CONFIG_FILES([Makefile xlators/performance/io-cache/src/Makefile xlators/performance/symlink-cache/Makefile xlators/performance/symlink-cache/src/Makefile + xlators/performance/quick-read/Makefile + xlators/performance/quick-read/src/Makefile xlators/debug/Makefile xlators/debug/trace/Makefile xlators/debug/trace/src/Makefile diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index a5a63ebaa..8f7616929 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -382,7 +382,6 @@ _fd_unref (fd_t *fd) static void fd_destroy (fd_t *fd) { - data_pair_t *pair = NULL; xlator_t *xl = NULL; int i = 0; @@ -399,26 +398,6 @@ fd_destroy (fd_t *fd) goto out; if (S_ISDIR (fd->inode->st_mode)) { - for (pair = fd->ctx->members_list; pair; pair = pair->next) { - /* notify all xlators which have a context */ - xl = xlator_search_by_name (fd->inode->table->xl, - pair->key); - - if (!xl) { - gf_log ("fd", GF_LOG_CRITICAL, - "fd(%p)->ctx has invalid key(%s)", - fd, pair->key); - continue; - } - if (xl->cbks->releasedir) { - xl->cbks->releasedir (xl, fd); - } else { - gf_log ("fd", GF_LOG_CRITICAL, - "xlator(%s) in fd(%p) no RELEASE cbk", - xl->name, fd); - } - - } for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) { if (fd->_ctx[i].key) { xl = (xlator_t *)(long)fd->_ctx[i].key; @@ -427,25 +406,6 @@ fd_destroy (fd_t *fd) } } } else { - for (pair = fd->ctx->members_list; pair; pair = pair->next) { - /* notify all xlators which have a context */ - xl = xlator_search_by_name (fd->inode->table->xl, - pair->key); - - if (!xl) { - gf_log ("fd", GF_LOG_CRITICAL, - "fd(%p)->ctx has invalid key(%s)", - fd, pair->key); - continue; - } - if (xl->cbks->release) { - xl->cbks->release (xl, fd); - } else { - gf_log ("fd", GF_LOG_CRITICAL, - "xlator(%s) in fd(%p) no RELEASE cbk", - xl->name, fd); - } - } for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) { if (fd->_ctx[i].key) { xl = (xlator_t *)(long)fd->_ctx[i].key; @@ -460,7 +420,6 @@ fd_destroy (fd_t *fd) FREE (fd->_ctx); inode_unref (fd->inode); fd->inode = (inode_t *)0xaaaaaaaa; - dict_destroy (fd->ctx); FREE (fd); out: @@ -525,7 +484,6 @@ fd_create (inode_t *inode, pid_t pid) fd->_ctx = CALLOC (1, (sizeof (struct _fd_ctx) * inode->table->xl->ctx->xl_count)); - fd->ctx = get_new_dict (); fd->inode = inode_ref (inode); fd->pid = pid; INIT_LIST_HEAD (&fd->inode_list); diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index 298b1b347..1770658e8 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -48,7 +48,6 @@ struct _fd { int32_t refcount; struct list_head inode_list; struct _inode *inode; - struct _dict *ctx; gf_lock_t lock; /* used ONLY for manipulating 'struct _fd_ctx' array (_ctx).*/ struct _fd_ctx *_ctx; diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index b0c9abd98..858f7e14d 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -235,32 +235,8 @@ static void __inode_destroy (inode_t *inode) { int index = 0; - data_pair_t *pair = NULL; xlator_t *xl = NULL; - if (!inode->ctx) { - goto noctx; - } - for (pair = inode->ctx->members_list; pair; pair = pair->next) { - /* notify all xlators which have a context */ - xl = xlator_search_by_name (inode->table->xl, pair->key); - - if (!xl) { - gf_log (inode->table->name, GF_LOG_DEBUG, - "inode(%"PRId64")->ctx has invalid key(%s)", - inode->ino, pair->key); - continue; - } - - if (xl->cbks->forget) - xl->cbks->forget (xl, inode); - else - gf_log (inode->table->name, GF_LOG_DEBUG, - "xlator(%s) in inode(%"PRId64") no FORGET fop", - xl->name, inode->ino); - } - dict_destroy (inode->ctx); - if (!inode->_ctx) goto noctx; @@ -450,8 +426,6 @@ __inode_create (inode_table_t *table) newi->_ctx = CALLOC (1, (sizeof (struct _inode_ctx) * table->xl->ctx->xl_count)); - newi->ctx = get_new_dict (); - return newi; } @@ -859,6 +833,13 @@ inode_path (inode_t *inode, trav = __dentry_search_arbit (trav->parent)) { i ++; /* "/" */ i += strlen (trav->name); + if (i > PATH_MAX) { + gf_log ("inode", GF_LOG_CRITICAL, + "possible infinite loop detected, " + "forcing break. name=(%s)", name); + ret = -ENOENT; + goto unlock; + } } if ((inode->ino != 1) && diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 8800b9767..e71c6d899 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -83,7 +83,6 @@ struct _inode { uint64_t generation; uint32_t ref; /* reference count on this inode */ ino_t ino; /* inode number in the storage (persistent) */ - dict_t *ctx; /* per xlator private */ mode_t st_mode; /* what kind of file */ struct list_head fd_list; /* list of open files on this inode */ struct list_head dentry_list; /* list of directory entries for this inode */ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 6f5da84b4..351e24344 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -247,7 +247,15 @@ _volume_option_value_validate (xlator_t *xl, switch (opt->type) { case GF_OPTION_TYPE_PATH: { - /* Make sure the given path is valid */ + if (strstr (pair->value->data, "../")) { + gf_log (xl->name, GF_LOG_ERROR, + "invalid path given '%s'", + pair->value->data); + ret = -1; + goto out; + } + + /* Make sure the given path is valid */ if (pair->value->data[0] != '/') { gf_log (xl->name, GF_LOG_WARNING, "option %s %s: '%s' is not an " diff --git a/transport/ib-verbs/src/ib-verbs.c b/transport/ib-verbs/src/ib-verbs.c index 6b5123284..469287489 100644 --- a/transport/ib-verbs/src/ib-verbs.c +++ b/transport/ib-verbs/src/ib-verbs.c @@ -397,7 +397,7 @@ ib_verbs_writev (transport_t *this, peer = &priv->peer; if (list_empty (&peer->ioq)) { ret = __ib_verbs_ioq_churn_entry (peer, entry); - if (ret > 0) { + if (ret != 0) { need_append = 0; } } diff --git a/xlators/cluster/afr/src/afr-dir-write.c b/xlators/cluster/afr/src/afr-dir-write.c index b07ac3c48..88a3ded5e 100644 --- a/xlators/cluster/afr/src/afr-dir-write.c +++ b/xlators/cluster/afr/src/afr-dir-write.c @@ -78,6 +78,7 @@ afr_create_unwind (call_frame_t *frame, xlator_t *this) { call_frame_t *main_frame = NULL; afr_local_t *local = NULL; + struct stat *unwind_buf = NULL; local = frame->local; @@ -91,10 +92,16 @@ afr_create_unwind (call_frame_t *frame, xlator_t *this) UNLOCK (&frame->lock); if (main_frame) { + if (local->cont.create.read_child_buf.st_ino) { + unwind_buf = &local->cont.create.read_child_buf; + } else { + unwind_buf = &local->cont.create.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, local->cont.create.fd, local->cont.create.inode, - &local->cont.create.buf); + unwind_buf); } return 0; @@ -155,13 +162,7 @@ afr_create_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (child_index == local->read_child_index) { - if (priv->read_child >= 0) { - afr_set_read_child (this, inode, - priv->read_child); - } else { - afr_set_read_child (this, inode, - local->read_child_index); - } + local->cont.create.read_child_buf = *buf; } local->cont.create.inode = inode; @@ -321,6 +322,8 @@ afr_mknod_unwind (call_frame_t *frame, xlator_t *this) call_frame_t *main_frame = NULL; afr_local_t *local = NULL; + struct stat *unwind_buf = NULL; + local = frame->local; LOCK (&frame->lock); @@ -333,9 +336,15 @@ afr_mknod_unwind (call_frame_t *frame, xlator_t *this) UNLOCK (&frame->lock); if (main_frame) { + if (local->cont.mknod.read_child_buf.st_ino) { + unwind_buf = &local->cont.mknod.read_child_buf; + } else { + unwind_buf = &local->cont.mknod.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, local->cont.mknod.inode, - &local->cont.mknod.buf); + unwind_buf); } return 0; @@ -383,13 +392,7 @@ afr_mknod_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (child_index == local->read_child_index) { - if (priv->read_child >= 0) { - afr_set_read_child (this, inode, - priv->read_child); - } else { - afr_set_read_child (this, inode, - local->read_child_index); - } + local->cont.mknod.read_child_buf = *buf; } local->cont.mknod.inode = inode; @@ -545,6 +548,8 @@ afr_mkdir_unwind (call_frame_t *frame, xlator_t *this) call_frame_t *main_frame = NULL; afr_local_t *local = NULL; + struct stat *unwind_buf = NULL; + local = frame->local; LOCK (&frame->lock); @@ -557,9 +562,15 @@ afr_mkdir_unwind (call_frame_t *frame, xlator_t *this) UNLOCK (&frame->lock); if (main_frame) { + if (local->cont.mkdir.read_child_buf.st_ino) { + unwind_buf = &local->cont.mkdir.read_child_buf; + } else { + unwind_buf = &local->cont.mkdir.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, local->cont.mkdir.inode, - &local->cont.mkdir.buf); + unwind_buf); } return 0; @@ -606,13 +617,7 @@ afr_mkdir_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (child_index == local->read_child_index) { - if (priv->read_child >= 0) { - afr_set_read_child (this, inode, - priv->read_child); - } else { - afr_set_read_child (this, inode, - local->read_child_index); - } + local->cont.mkdir.read_child_buf = *buf; } local->cont.mkdir.inode = inode; @@ -769,6 +774,8 @@ afr_link_unwind (call_frame_t *frame, xlator_t *this) call_frame_t *main_frame = NULL; afr_local_t *local = NULL; + struct stat *unwind_buf = NULL; + local = frame->local; LOCK (&frame->lock); @@ -783,9 +790,15 @@ afr_link_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.link.buf.st_ino = local->cont.link.ino; + if (local->cont.link.read_child_buf.st_ino) { + unwind_buf = &local->cont.link.read_child_buf; + } else { + unwind_buf = &local->cont.link.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, local->cont.link.inode, - &local->cont.link.buf); + unwind_buf); } return 0; @@ -832,13 +845,7 @@ afr_link_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (child_index == local->read_child_index) { - if (priv->read_child >= 0) { - afr_set_read_child (this, inode, - priv->read_child); - } else { - afr_set_read_child (this, inode, - local->read_child_index); - } + local->cont.link.read_child_buf = *buf; } local->cont.link.inode = inode; @@ -994,7 +1001,9 @@ afr_symlink_unwind (call_frame_t *frame, xlator_t *this) { call_frame_t *main_frame = NULL; afr_local_t *local = NULL; - + + struct stat *unwind_buf = NULL; + local = frame->local; LOCK (&frame->lock); @@ -1007,9 +1016,15 @@ afr_symlink_unwind (call_frame_t *frame, xlator_t *this) UNLOCK (&frame->lock); if (main_frame) { + if (local->cont.symlink.read_child_buf.st_ino) { + unwind_buf = &local->cont.symlink.read_child_buf; + } else { + unwind_buf = &local->cont.symlink.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, local->cont.symlink.inode, - &local->cont.symlink.buf); + unwind_buf); } return 0; @@ -1056,13 +1071,7 @@ afr_symlink_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (child_index == local->read_child_index) { - if (priv->read_child >= 0) { - afr_set_read_child (this, inode, - priv->read_child); - } else { - afr_set_read_child (this, inode, - local->read_child_index); - } + local->cont.symlink.read_child_buf = *buf; } local->cont.symlink.inode = inode; @@ -1219,6 +1228,8 @@ afr_rename_unwind (call_frame_t *frame, xlator_t *this) call_frame_t *main_frame = NULL; afr_local_t *local = NULL; + struct stat *unwind_buf = NULL; + local = frame->local; LOCK (&frame->lock); @@ -1233,8 +1244,14 @@ afr_rename_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.rename.buf.st_ino = local->cont.rename.ino; + if (local->cont.rename.read_child_buf.st_ino) { + unwind_buf = &local->cont.rename.read_child_buf; + } else { + unwind_buf = &local->cont.rename.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.rename.buf); + unwind_buf); } return 0; @@ -1261,17 +1278,23 @@ afr_rename_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); - if ((op_ret != -1) && (local->success_count == 0)) { - local->op_ret = op_ret; + if (op_ret != -1) { + if (local->success_count == 0) { + local->op_ret = op_ret; - if (buf) { - local->cont.rename.buf = *buf; - local->cont.rename.buf.st_ino = - afr_itransform (buf->st_ino, priv->child_count, - child_index); - } - local->success_count++; - } + if (buf) { + local->cont.rename.buf = *buf; + local->cont.rename.buf.st_ino = + afr_itransform (buf->st_ino, priv->child_count, + child_index); + } + local->success_count++; + } + + if (child_index == local->read_child_index) { + local->cont.rename.read_child_buf = *buf; + } + } local->op_errno = op_errno; } @@ -1379,6 +1402,8 @@ afr_rename (call_frame_t *frame, xlator_t *this, loc_copy (&local->loc, oldloc); loc_copy (&local->newloc, newloc); + local->read_child_index = afr_read_child (this, oldloc->inode); + local->cont.rename.ino = oldloc->inode->ino; local->transaction.fop = afr_rename_wind; diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c index 57fdf20d5..1c1a9b034 100644 --- a/xlators/cluster/afr/src/afr-inode-write.c +++ b/xlators/cluster/afr/src/afr-inode-write.c @@ -58,6 +58,8 @@ afr_chmod_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -71,8 +73,15 @@ afr_chmod_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.chmod.buf.st_ino = local->cont.chmod.ino; + + if (local->cont.chmod.read_child_buf.st_ino) { + unwind_buf = &local->cont.chmod.read_child_buf; + } else { + unwind_buf = &local->cont.chmod.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.chmod.buf); + unwind_buf); } return 0; } @@ -88,12 +97,19 @@ afr_chmod_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int call_count = -1; int child_index = (long) cookie; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->loc.inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -102,9 +118,15 @@ afr_chmod_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.chmod.buf = *buf; } + + if (child_index == read_child) { + local->cont.chmod.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -251,6 +273,7 @@ afr_fchmod_unwind (call_frame_t *frame, xlator_t *this) afr_local_t * local = NULL; afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat *unwind_buf = NULL; local = frame->local; priv = this->private; @@ -265,8 +288,15 @@ afr_fchmod_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.fchmod.buf.st_ino = local->cont.fchmod.ino; + + if (local->cont.fchmod.read_child_buf.st_ino) { + unwind_buf = &local->cont.fchmod.read_child_buf; + } else { + unwind_buf = &local->cont.fchmod.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.fchmod.buf); + unwind_buf); } return 0; } @@ -282,12 +312,19 @@ afr_fchmod_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int call_count = -1; int child_index = (long) cookie; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->fd->inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -296,9 +333,15 @@ afr_fchmod_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.fchmod.buf = *buf; } + + if (child_index == read_child) { + local->cont.fchmod.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -445,6 +488,8 @@ afr_chown_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -458,8 +503,15 @@ afr_chown_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.chown.buf.st_ino = local->cont.chown.ino; + + if (local->cont.chown.read_child_buf.st_ino) { + unwind_buf = &local->cont.chown.read_child_buf; + } else { + unwind_buf = &local->cont.chown.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.chown.buf); + unwind_buf); } return 0; } @@ -475,12 +527,19 @@ afr_chown_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int call_count = -1; int child_index = (long) cookie; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->loc.inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -489,9 +548,15 @@ afr_chown_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.chown.buf = *buf; } + + if (child_index == read_child) { + local->cont.chown.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -642,6 +707,8 @@ afr_fchown_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -655,8 +722,15 @@ afr_fchown_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.fchown.buf.st_ino = local->cont.fchown.ino; + + if (local->cont.fchown.read_child_buf.st_ino) { + unwind_buf = &local->cont.fchown.read_child_buf; + } else { + unwind_buf = &local->cont.fchown.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.fchown.buf); + unwind_buf); } return 0; } @@ -672,12 +746,19 @@ afr_fchown_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int call_count = -1; int child_index = (long) cookie; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->fd->inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -686,9 +767,15 @@ afr_fchown_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.fchown.buf = *buf; } + + if (child_index == read_child) { + local->cont.fchown.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -838,6 +925,8 @@ afr_writev_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -851,8 +940,15 @@ afr_writev_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.writev.buf.st_ino = local->cont.writev.ino; + + if (local->cont.writev.read_child_buf.st_ino) { + unwind_buf = &local->cont.writev.read_child_buf; + } else { + unwind_buf = &local->cont.writev.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.writev.buf); + unwind_buf); } return 0; } @@ -868,12 +964,19 @@ afr_writev_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int child_index = (long) cookie; int call_count = -1; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->fd->inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -882,9 +985,15 @@ afr_writev_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.writev.buf = *buf; } + + if (child_index == read_child) { + local->cont.writev.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -1049,6 +1158,8 @@ afr_truncate_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -1062,9 +1173,18 @@ afr_truncate_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.truncate.buf.st_ino = local->cont.truncate.ino; - AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.truncate.buf); - } + + if (local->cont.truncate.read_child_buf.st_ino) { + unwind_buf = &local->cont.truncate.read_child_buf; + } else { + unwind_buf = &local->cont.truncate.buf; + } + + AFR_STACK_UNWIND (main_frame, local->op_ret, + local->op_errno, + unwind_buf); + } + return 0; } @@ -1077,14 +1197,21 @@ afr_truncate_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, afr_private_t * priv = NULL; int child_index = (long) cookie; + int read_child = 0; int call_count = -1; int need_unwind = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->loc.inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -1093,9 +1220,15 @@ afr_truncate_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.truncate.buf = *buf; } + + if (child_index == read_child) { + local->cont.truncate.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -1247,6 +1380,8 @@ afr_ftruncate_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -1260,8 +1395,15 @@ afr_ftruncate_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.ftruncate.buf.st_ino = local->cont.ftruncate.ino; + + if (local->cont.ftruncate.read_child_buf.st_ino) { + unwind_buf = &local->cont.ftruncate.read_child_buf; + } else { + unwind_buf = &local->cont.ftruncate.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.ftruncate.buf); + unwind_buf); } return 0; } @@ -1277,12 +1419,19 @@ afr_ftruncate_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int child_index = (long) cookie; int call_count = -1; int need_unwind = 0; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->fd->inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -1291,9 +1440,15 @@ afr_ftruncate_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.ftruncate.buf = *buf; } + + if (child_index == read_child) { + local->cont.ftruncate.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } @@ -1444,6 +1599,8 @@ afr_utimens_unwind (call_frame_t *frame, xlator_t *this) afr_private_t * priv = NULL; call_frame_t *main_frame = NULL; + struct stat * unwind_buf = NULL; + local = frame->local; priv = this->private; @@ -1457,8 +1614,15 @@ afr_utimens_unwind (call_frame_t *frame, xlator_t *this) if (main_frame) { local->cont.utimens.buf.st_ino = local->cont.utimens.ino; + + if (local->cont.utimens.read_child_buf.st_ino) { + unwind_buf = &local->cont.utimens.read_child_buf; + } else { + unwind_buf = &local->cont.utimens.buf; + } + AFR_STACK_UNWIND (main_frame, local->op_ret, local->op_errno, - &local->cont.utimens.buf); + unwind_buf); } return 0; } @@ -1474,12 +1638,19 @@ afr_utimens_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int child_index = (long) cookie; int call_count = -1; int need_unwind = 1; + int read_child = 0; local = frame->local; priv = this->private; + read_child = afr_read_child (this, local->loc.inode); + LOCK (&frame->lock); { + if (child_index == read_child) { + local->read_child_returned = _gf_true; + } + if (afr_fop_failed (op_ret, op_errno)) afr_transaction_fop_failed (frame, this, child_index); @@ -1488,9 +1659,15 @@ afr_utimens_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->cont.utimens.buf = *buf; } + + if (child_index == read_child) { + local->cont.utimens.read_child_buf = *buf; + } + local->success_count++; - if (local->success_count == priv->wait_count) { + if ((local->success_count >= priv->wait_count) + && local->read_child_returned) { need_unwind = 1; } } diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index 31c81ffd4..33aa16157 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -62,7 +62,9 @@ afr_is_split_brain (xlator_t *this, inode_t *inode) uint64_t ctx = 0; uint64_t split_brain = 0; - + + VALIDATE_OR_GOTO (inode, out); + LOCK (&inode->lock); { ret = __inode_ctx_get (inode, this, &ctx); @@ -75,6 +77,7 @@ afr_is_split_brain (xlator_t *this, inode_t *inode) unlock: UNLOCK (&inode->lock); +out: return split_brain; } @@ -85,6 +88,8 @@ afr_set_split_brain (xlator_t *this, inode_t *inode, int32_t split_brain) uint64_t ctx = 0; int ret = 0; + VALIDATE_OR_GOTO (inode, out); + LOCK (&inode->lock); { ret = __inode_ctx_get (inode, this, &ctx); @@ -99,6 +104,8 @@ afr_set_split_brain (xlator_t *this, inode_t *inode, int32_t split_brain) __inode_ctx_put (inode, this, ctx); } UNLOCK (&inode->lock); +out: + return; } @@ -109,7 +116,9 @@ afr_read_child (xlator_t *this, inode_t *inode) uint64_t ctx = 0; uint64_t read_child = 0; - + + VALIDATE_OR_GOTO (inode, out); + LOCK (&inode->lock); { ret = __inode_ctx_get (inode, this, &ctx); @@ -122,6 +131,7 @@ afr_read_child (xlator_t *this, inode_t *inode) unlock: UNLOCK (&inode->lock); +out: return read_child; } @@ -132,6 +142,8 @@ afr_set_read_child (xlator_t *this, inode_t *inode, int32_t read_child) uint64_t ctx = 0; int ret = 0; + VALIDATE_OR_GOTO (inode, out); + LOCK (&inode->lock); { ret = __inode_ctx_get (inode, this, &ctx); @@ -146,6 +158,9 @@ afr_set_read_child (xlator_t *this, inode_t *inode, int32_t read_child) __inode_ctx_put (inode, this, ctx); } UNLOCK (&inode->lock); + +out: + return; } @@ -486,6 +501,16 @@ afr_lookup_cbk (call_frame_t *frame, void *cookie, &open_fd_count); local->open_fd_count += open_fd_count; + + first_up_child = afr_first_up_child (priv); + + if (child_index == first_up_child) { + local->cont.lookup.ino = + afr_itransform (buf->st_ino, + priv->child_count, + first_up_child); + } + /* in case of revalidate, we need to send stat of the * child whose stat was sent during the first lookup. * (so that time stamp does not vary with revalidate. @@ -540,15 +565,6 @@ afr_lookup_cbk (call_frame_t *frame, void *cookie, local->need_data_self_heal = 1; } - first_up_child = afr_first_up_child (priv); - - if (child_index == first_up_child) { - local->cont.lookup.buf.st_ino = - afr_itransform (buf->st_ino, - priv->child_count, - first_up_child); - } - if (child_index == local->read_child_index) { /* @@ -587,11 +603,15 @@ unlock: call_count = afr_frame_return (frame); if (call_count == 0) { + if (local->cont.lookup.ino) { + local->cont.lookup.buf.st_ino = local->cont.lookup.ino; + } + if (local->op_ret == 0) { /* KLUDGE: assuming DHT will not itransform in revalidate */ if (local->cont.lookup.inode->ino) - lookup_buf->st_ino = + local->cont.lookup.buf.st_ino = local->cont.lookup.inode->ino; } @@ -722,6 +742,9 @@ afr_fd_ctx_set (xlator_t *this, fd_t *fd) uint64_t ctx; afr_fd_ctx_t * fd_ctx = NULL; + VALIDATE_OR_GOTO (this->private, out); + VALIDATE_OR_GOTO (fd, out); + priv = this->private; LOCK (&fd->lock); @@ -729,7 +752,7 @@ afr_fd_ctx_set (xlator_t *this, fd_t *fd) ret = __fd_ctx_get (fd, this, &ctx); if (ret == 0) - goto out; + goto unlock; fd_ctx = CALLOC (1, sizeof (afr_fd_ctx_t)); if (!fd_ctx) { @@ -737,7 +760,7 @@ afr_fd_ctx_set (xlator_t *this, fd_t *fd) "Out of memory"); op_ret = -ENOMEM; - goto out; + goto unlock; } fd_ctx->child_failed = CALLOC (sizeof (*fd_ctx->child_failed), @@ -748,7 +771,7 @@ afr_fd_ctx_set (xlator_t *this, fd_t *fd) "Out of memory"); op_ret = -ENOMEM; - goto out; + goto unlock; } ret = __fd_ctx_set (fd, this, (uint64_t)(long) fd_ctx); @@ -756,9 +779,9 @@ afr_fd_ctx_set (xlator_t *this, fd_t *fd) op_ret = ret; } } -out: +unlock: UNLOCK (&fd->lock); - +out: return ret; } diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index 2871bfc47..87ef26333 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -145,6 +145,7 @@ typedef struct _afr_local { unsigned int govinda_gOvinda; unsigned int read_child_index; + unsigned char read_child_returned; pid_t saved_pid; @@ -182,6 +183,8 @@ typedef struct _afr_local { struct { inode_t *inode; struct stat buf; + struct stat read_child_buf; + ino_t ino; dict_t *xattr; } lookup; @@ -267,12 +270,14 @@ typedef struct _afr_local { ino_t ino; mode_t mode; struct stat buf; + struct stat read_child_buf; } chmod; struct { ino_t ino; mode_t mode; struct stat buf; + struct stat read_child_buf; } fchmod; struct { @@ -280,6 +285,7 @@ typedef struct _afr_local { uid_t uid; gid_t gid; struct stat buf; + struct stat read_child_buf; } chown; struct { @@ -287,11 +293,13 @@ typedef struct _afr_local { uid_t uid; gid_t gid; struct stat buf; + struct stat read_child_buf; } fchown; struct { ino_t ino; struct stat buf; + struct stat read_child_buf; int32_t op_ret; @@ -305,18 +313,21 @@ typedef struct _afr_local { ino_t ino; off_t offset; struct stat buf; + struct stat read_child_buf; } truncate; struct { ino_t ino; off_t offset; struct stat buf; + struct stat read_child_buf; } ftruncate; struct { ino_t ino; struct timespec tv[2]; struct stat buf; + struct stat read_child_buf; } utimens; struct { @@ -337,6 +348,7 @@ typedef struct _afr_local { mode_t mode; inode_t *inode; struct stat buf; + struct stat read_child_buf; } create; struct { @@ -345,6 +357,7 @@ typedef struct _afr_local { mode_t mode; inode_t *inode; struct stat buf; + struct stat read_child_buf; } mknod; struct { @@ -352,6 +365,7 @@ typedef struct _afr_local { int32_t mode; inode_t *inode; struct stat buf; + struct stat read_child_buf; } mkdir; struct { @@ -367,18 +381,21 @@ typedef struct _afr_local { struct { ino_t ino; struct stat buf; + struct stat read_child_buf; } rename; struct { ino_t ino; inode_t *inode; struct stat buf; + struct stat read_child_buf; } link; struct { ino_t ino; inode_t *inode; struct stat buf; + struct stat read_child_buf; char *linkpath; } symlink; diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c index 2a46f4d78..c07685017 100644 --- a/xlators/debug/io-stats/src/io-stats.c +++ b/xlators/debug/io-stats/src/io-stats.c @@ -43,6 +43,22 @@ do { \ UNLOCK (&((io_stats_private_t *)this->private)->lock); \ } while (0) +struct io_stats_io_count { + size_t size; + int64_t hits; +}; +typedef enum { + GF_IO_STAT_BLK_SIZE_1K, + GF_IO_STAT_BLK_SIZE_2K, + GF_IO_STAT_BLK_SIZE_4K, + GF_IO_STAT_BLK_SIZE_8K, + GF_IO_STAT_BLK_SIZE_16K, + GF_IO_STAT_BLK_SIZE_32K, + GF_IO_STAT_BLK_SIZE_64K, + GF_IO_STAT_BLK_SIZE_128K, + GF_IO_STAT_BLK_SIZE_MAX, +} gf_io_stat_blk_t; + struct io_stats_private { gf_lock_t lock; struct { @@ -50,6 +66,8 @@ struct io_stats_private { int enabled; uint32_t hits; } fop_records[GF_FOP_MAXVALUE]; + struct io_stats_io_count read[GF_IO_STAT_BLK_SIZE_MAX + 1]; + struct io_stats_io_count write[GF_IO_STAT_BLK_SIZE_MAX + 1]; }; typedef struct io_stats_private io_stats_private_t; @@ -102,6 +120,20 @@ io_stats_readv_cbk (call_frame_t *frame, struct stat *buf, struct iobref *iobref) { + int i = 0; + io_stats_private_t *priv = NULL; + + priv = this->private; + + if (op_ret > 0) { + for (i=0; i < GF_IO_STAT_BLK_SIZE_MAX; i++) { + if (priv->read[i].size > iov_length (vector, count)) { + break; + } + } + priv->read[i].hits++; + } + STACK_UNWIND (frame, op_ret, op_errno, vector, count, buf, iobref); return 0; } @@ -966,8 +998,20 @@ io_stats_writev (call_frame_t *frame, off_t offset, struct iobref *iobref) { + int i = 0; + io_stats_private_t *priv = NULL; + + priv = this->private; + BUMP_HIT(WRITE); + for (i=0; i < GF_IO_STAT_BLK_SIZE_MAX; i++) { + if (priv->write[i].size > iov_length (vector, count)) { + break; + } + } + priv->write[i].hits++; + STACK_WIND (frame, io_stats_writev_cbk, FIRST_CHILD(this), @@ -1386,6 +1430,8 @@ init (xlator_t *this) dict_t *options = this->options; char *includes = NULL, *excludes = NULL; io_stats_private_t *priv = NULL; + size_t size = 0; + int i = 0; if (!this) return -1; @@ -1406,18 +1452,15 @@ init (xlator_t *this) includes = data_to_str (dict_get (options, "include-ops")); excludes = data_to_str (dict_get (options, "exclude-ops")); - { - int i; - for (i = 0; i < GF_FOP_MAXVALUE; i++) { - priv->fop_records[i].name = gf_fop_list[i]; - priv->fop_records[i].enabled = 1; - } + for (i = 0; i < GF_FOP_MAXVALUE; i++) { + priv->fop_records[i].name = gf_fop_list[i]; + priv->fop_records[i].enabled = 1; } if (includes && excludes) { - gf_log (this->name, - GF_LOG_ERROR, - "must specify only one of 'include-ops' and 'exclude-ops'"); + gf_log (this->name, GF_LOG_ERROR, + "must specify only one of 'include-ops' and " + "'exclude-ops'"); return -1; } if (includes) @@ -1428,6 +1471,13 @@ init (xlator_t *this) LOCK_INIT (&priv->lock); /* Set this translator's inode table pointer to child node's pointer. */ + size = GF_UNIT_KB; + for (i=0; i < GF_IO_STAT_BLK_SIZE_MAX; i++) { + priv->read[i].size = size; + priv->write[i].size = size; + size *= 2; + } + this->itable = FIRST_CHILD (this)->itable; this->private = priv; diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index ff68123df..efc8ea54d 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -84,11 +84,29 @@ typedef struct fuse_private fuse_private_t; #define FUSE_FOP(state, ret, op_num, fop, args ...) \ do { \ - call_frame_t *frame = get_call_frame_for_req (state, 1); \ - xlator_t *xl = frame->this->children ? \ + call_frame_t *frame = NULL; \ + xlator_t *xl = NULL; \ + \ + frame = get_call_frame_for_req (state, 1); \ + if (!frame) { \ + /* This is not completely clean, as some \ + * earlier allocations might remain unfreed \ + * if we return at this point, but still \ + * better than trying to go on with a NULL \ + * frame ... \ + */ \ + gf_log ("glusterfs-fuse", \ + GF_LOG_ERROR, \ + "FUSE message unique %"PRIu64":" \ + " frame allocation failed", \ + req_callid (state->req)); \ + free_state (state); \ + return; \ + } \ + xl = frame->this->children ? \ frame->this->children->xlator : NULL; \ frame->root->state = state; \ - frame->root->op = op_num; \ + frame->root->op = op_num; \ STACK_WIND (frame, ret, xl, xl->fops->fop, args); \ } while (0) @@ -96,6 +114,23 @@ typedef struct fuse_private fuse_private_t; (((_errno == ENOENT) || (_errno == ESTALE))? \ GF_LOG_DEBUG) +#define STATE_FROM_REQ(req, state) \ + do { \ + state = state_from_req (req); \ + if (!state) { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_ERROR, \ + "FUSE message unique %"PRIu64":" \ + " state allocation failed", \ + req_callid (req)); \ + \ + fuse_reply_err (req, ENOMEM); \ + \ + return; \ + } \ + } while (0) + + typedef struct { void *pool; xlator_t *this; @@ -194,6 +229,8 @@ get_call_frame_for_req (fuse_state_t *state, char d) priv = this->private; frame = create_frame (this, pool); + if (!frame) + return NULL; if (req) { ctx = fuse_req_ctx (req); @@ -418,13 +455,13 @@ fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": LOOKUP %"PRId64"/%s (fuse_loc_fill() failed)", + "%"PRIu64": LOOKUP %"PRId64"/%s (fuse_loc_fill() failed)", req_callid (req), (ino_t)par, name); free_state (state); fuse_reply_err (req, ENOENT); @@ -433,7 +470,7 @@ fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name) if (!state->loc.inode) { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": LOOKUP %s", req_callid (req), + "%"PRIu64": LOOKUP %s", req_callid (req), state->loc.path); state->loc.inode = inode_new (state->itable); @@ -441,7 +478,7 @@ fuse_lookup (fuse_req_t req, fuse_ino_t par, const char *name) state->is_revalidate = -1; } else { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": LOOKUP %s(%"PRId64")", req_callid (req), + "%"PRIu64": LOOKUP %s(%"PRId64")", req_callid (req), state->loc.path, state->loc.inode->ino); state->is_revalidate = 1; } @@ -457,15 +494,16 @@ static void fuse_forget (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) { inode_t *fuse_inode; - fuse_state_t *state; + xlator_t *this = NULL; + + this = fuse_req_userdata (req); if (ino == 1) { fuse_reply_none (req); return; } - state = state_from_req (req); - fuse_inode = inode_search (state->itable, ino, NULL); + fuse_inode = inode_search (this->itable, ino, NULL); if (fuse_inode) { gf_log ("glusterfs-fuse", GF_LOG_TRACE, "got forget on inode (%lu)", ino); @@ -476,7 +514,6 @@ fuse_forget (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) "got forget, but inode (%lu) not found", ino); } - free_state (state); fuse_reply_none (req); } @@ -528,13 +565,13 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); if (ino == 1) { ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": GETATTR %"PRId64" (fuse_loc_fill() failed)", + "%"PRIu64": GETATTR %"PRId64" (fuse_loc_fill() failed)", req_callid (req), (ino_t)ino); fuse_reply_err (req, ENOENT); free_state (state); @@ -557,7 +594,7 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) if (!state->loc.inode) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": GETATTR %"PRId64" (%s) (fuse_loc_fill() returned NULL inode)", + "%"PRIu64": GETATTR %"PRId64" (%s) (fuse_loc_fill() returned NULL inode)", req_callid (req), (int64_t)ino, state->loc.path); fuse_reply_err (req, ENOENT); return; @@ -571,7 +608,7 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) */ if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": GETATTR %"PRId64" (fuse_loc_fill() failed)", + "%"PRIu64": GETATTR %"PRId64" (fuse_loc_fill() failed)", req_callid (req), (ino_t)ino); fuse_reply_err (req, ENOENT); free_state (state); @@ -579,7 +616,7 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": GETATTR %"PRId64" (%s)", + "%"PRIu64": GETATTR %"PRId64" (%s)", req_callid (req), (int64_t)ino, state->loc.path); @@ -588,7 +625,7 @@ fuse_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) } else { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FGETATTR %"PRId64" (%s/%p)", + "%"PRIu64": FGETATTR %"PRId64" (%s/%p)", req_callid (req), (int64_t)ino, state->loc.path, fd); FUSE_FOP (state,fuse_attr_cbk, GF_FOP_FSTAT, @@ -615,7 +652,8 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fi.flags = state->flags; if (!S_ISDIR (fd->inode->st_mode)) { - if ((fi.flags & 3) && priv->direct_io_mode) + if (((fi.flags & O_ACCMODE) != O_RDONLY) && + priv->direct_io_mode) fi.direct_io = 1; } @@ -655,7 +693,7 @@ do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr, fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); if (fi) { fd = FI_TO_FD (fi); state->fd = fd; @@ -663,7 +701,7 @@ do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if (fd) { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FCHMOD %p", req_callid (req), fd); + "%"PRIu64": FCHMOD %p", req_callid (req), fd); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHMOD, fchmod, fd, attr->st_mode); @@ -673,7 +711,7 @@ do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": CHMOD %"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": CHMOD %"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), (int64_t)ino, state->loc.path); fuse_reply_err (req, ENOENT); @@ -683,7 +721,7 @@ do_chmod (fuse_req_t req, fuse_ino_t ino, struct stat *attr, gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": CHMOD %s", req_callid (req), + "%"PRIu64": CHMOD %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHMOD, @@ -704,7 +742,7 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr, uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1; gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); if (fi) { fd = FI_TO_FD (fi); @@ -713,7 +751,7 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if (fd) { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FCHOWN %p", req_callid (req), fd); + "%"PRIu64": FCHOWN %p", req_callid (req), fd); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FCHOWN, fchown, fd, uid, gid); @@ -722,7 +760,7 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": CHOWN %"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": CHOWN %"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), (int64_t)ino, state->loc.path); fuse_reply_err (req, ENOENT); @@ -731,7 +769,7 @@ do_chown (fuse_req_t req, fuse_ino_t ino, struct stat *attr, } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": CHOWN %s", req_callid (req), + "%"PRIu64": CHOWN %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_CHOWN, @@ -748,7 +786,7 @@ do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr, fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); if (fi) { fd = FI_TO_FD (fi); @@ -757,7 +795,7 @@ do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if (fd) { gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FTRUNCATE %p/%"PRId64, req_callid (req), + "%"PRIu64": FTRUNCATE %p/%"PRId64, req_callid (req), fd, attr->st_size); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_FTRUNCATE, @@ -767,7 +805,7 @@ do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr, if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": TRUNCATE %s/%"PRId64" (fuse_loc_fill() failed)", + "%"PRIu64": TRUNCATE %s/%"PRId64" (fuse_loc_fill() failed)", req_callid (req), state->loc.path, attr->st_size); fuse_reply_err (req, ENOENT); @@ -776,7 +814,7 @@ do_truncate (fuse_req_t req, fuse_ino_t ino, struct stat *attr, } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": TRUNCATE %s/%"PRId64"(%lu)", + "%"PRIu64": TRUNCATE %s/%"PRId64"(%lu)", req_callid (req), state->loc.path, attr->st_size, ino); @@ -800,12 +838,12 @@ do_utimes (fuse_req_t req, fuse_ino_t ino, struct stat *attr) tv[1].tv_sec = attr->st_mtime; tv[1].tv_nsec = ST_ATIM_NSEC (attr); - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": UTIMENS %s (fuse_loc_fill() failed)", + "%"PRIu64": UTIMENS %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -813,7 +851,7 @@ do_utimes (fuse_req_t req, fuse_ino_t ino, struct stat *attr) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": UTIMENS (%lu)%s", req_callid (req), + "%"PRIu64": UTIMENS (%lu)%s", req_callid (req), ino, state->loc.path); FUSE_FOP (state, fuse_attr_cbk, GF_FOP_UTIMENS, @@ -936,13 +974,13 @@ fuse_access (fuse_req_t req, fuse_ino_t ino, int mask) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": ACCESS %"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": ACCESS %"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), (int64_t)ino, state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -950,7 +988,7 @@ fuse_access (fuse_req_t req, fuse_ino_t ino, int mask) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64" ACCESS %s/%lu mask=%d", req_callid (req), + "%"PRIu64" ACCESS %s/%lu mask=%d", req_callid (req), state->loc.path, ino, mask); FUSE_FOP (state, fuse_err_cbk, @@ -1000,12 +1038,12 @@ fuse_readlink (fuse_req_t req, fuse_ino_t ino) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64" READLINK %s/%"PRId64" (fuse_loc_fill() returned NULL inode)", + "%"PRIu64" READLINK %s/%"PRId64" (fuse_loc_fill() returned NULL inode)", req_callid (req), state->loc.path, state->loc.inode->ino); fuse_reply_err (req, ENOENT); @@ -1014,7 +1052,7 @@ fuse_readlink (fuse_req_t req, fuse_ino_t ino) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64" READLINK %s/%"PRId64, req_callid (req), + "%"PRIu64" READLINK %s/%"PRId64, req_callid (req), state->loc.path, state->loc.inode->ino); FUSE_FOP (state, fuse_readlink_cbk, GF_FOP_READLINK, @@ -1031,11 +1069,11 @@ fuse_mknod (fuse_req_t req, fuse_ino_t par, const char *name, fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64" MKNOD %s (fuse_loc_fill() failed)", + "%"PRIu64" MKNOD %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -1045,7 +1083,7 @@ fuse_mknod (fuse_req_t req, fuse_ino_t par, const char *name, state->loc.inode = inode_new (state->itable); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": MKNOD %s", req_callid (req), + "%"PRIu64": MKNOD %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKNOD, @@ -1061,11 +1099,11 @@ fuse_mkdir (fuse_req_t req, fuse_ino_t par, const char *name, mode_t mode) fuse_state_t *state; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64" MKDIR %s (fuse_loc_fill() failed)", + "%"PRIu64" MKDIR %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -1075,7 +1113,7 @@ fuse_mkdir (fuse_req_t req, fuse_ino_t par, const char *name, mode_t mode) state->loc.inode = inode_new (state->itable); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": MKDIR %s", req_callid (req), + "%"PRIu64": MKDIR %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_entry_cbk, GF_FOP_MKDIR, @@ -1091,14 +1129,14 @@ fuse_unlink (fuse_req_t req, fuse_ino_t par, const char *name) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": UNLINK %s (fuse_loc_fill() returned NULL inode)", + "%"PRIu64": UNLINK %s (fuse_loc_fill() returned NULL inode)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -1106,7 +1144,7 @@ fuse_unlink (fuse_req_t req, fuse_ino_t par, const char *name) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": UNLINK %s", req_callid (req), + "%"PRIu64": UNLINK %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_UNLINK, @@ -1122,12 +1160,12 @@ fuse_rmdir (fuse_req_t req, fuse_ino_t par, const char *name) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": RMDIR %s (fuse_loc_fill() failed)", + "%"PRIu64": RMDIR %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -1135,7 +1173,7 @@ fuse_rmdir (fuse_req_t req, fuse_ino_t par, const char *name) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": RMDIR %s", req_callid (req), + "%"PRIu64": RMDIR %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_unlink_cbk, GF_FOP_RMDIR, @@ -1152,11 +1190,11 @@ fuse_symlink (fuse_req_t req, const char *linkname, fuse_ino_t par, fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64" SYMLINK %s -> %s (fuse_loc_fill() failed)", + "%"PRIu64" SYMLINK %s -> %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path, linkname); fuse_reply_err (req, ENOENT); free_state (state); @@ -1166,7 +1204,7 @@ fuse_symlink (fuse_req_t req, const char *linkname, fuse_ino_t par, state->loc.inode = inode_new (state->itable); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": SYMLINK %s -> %s", req_callid (req), + "%"PRIu64": SYMLINK %s -> %s", req_callid (req), state->loc.path, linkname); FUSE_FOP (state, fuse_entry_cbk, GF_FOP_SYMLINK, @@ -1228,13 +1266,13 @@ fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname, fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, oldpar, oldname); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "for %s %"PRId64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)", + "for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)", state->loc.path, req_callid (req), state->loc.path, state->loc2.path); @@ -1246,7 +1284,7 @@ fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname, ret = fuse_loc_fill (&state->loc2, state, 0, newpar, newname); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "for %s %"PRId64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)", + "for %s %"PRIu64": RENAME `%s' -> `%s' (fuse_loc_fill() failed)", state->loc.path, req_callid (req), state->loc.path, state->loc2.path); @@ -1256,7 +1294,7 @@ fuse_rename (fuse_req_t req, fuse_ino_t oldpar, const char *oldname, } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'", + "%"PRIu64": RENAME `%s (%"PRId64")' -> `%s (%"PRId64")'", req_callid (req), state->loc.path, state->loc.ino, state->loc2.path, state->loc2.ino); @@ -1273,15 +1311,16 @@ fuse_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t par, const char *name) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 0, par, name); - ret = fuse_loc_fill (&state->loc2, state, ino, 0, NULL); + if (ret == 0) + ret = fuse_loc_fill (&state->loc2, state, ino, 0, NULL); if ((state->loc2.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "fuse_loc_fill() failed for %s %"PRId64": LINK %s %s", + "fuse_loc_fill() failed for %s %"PRIu64": LINK %s %s", state->loc2.path, req_callid (req), state->loc2.path, state->loc.path); fuse_reply_err (req, ENOENT); @@ -1291,7 +1330,7 @@ fuse_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t par, const char *name) state->loc.inode = inode_ref (state->loc2.inode); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": LINK() %s (%"PRId64") -> %s (%"PRId64")", + "%"PRIu64": LINK() %s (%"PRId64") -> %s (%"PRId64")", req_callid (req), state->loc2.path, state->loc2.ino, state->loc.path, state->loc.ino); @@ -1321,7 +1360,8 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret >= 0) { fi.fh = (unsigned long) fd; - if ((fi.flags & 3) && priv->direct_io_mode) + if (((fi.flags & O_ACCMODE) != O_RDONLY) + && priv->direct_io_mode) fi.direct_io = 1; gf_log ("glusterfs-fuse", GF_LOG_TRACE, @@ -1361,7 +1401,7 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fd_bind (fd); } else { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": %s => -1 (%s)", req_callid (req), + "%"PRIu64": %s => -1 (%s)", req_callid (req), state->loc.path, strerror (op_errno)); fuse_reply_err (req, op_errno); } @@ -1381,13 +1421,13 @@ fuse_create (fuse_req_t req, fuse_ino_t par, const char *name, fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->flags = fi->flags; ret = fuse_loc_fill (&state->loc, state, 0, par, name); if (ret < 0) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64" CREATE %s (fuse_loc_fill() failed)", + "%"PRIu64" CREATE %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); free_state (state); @@ -1401,7 +1441,7 @@ fuse_create (fuse_req_t req, fuse_ino_t par, const char *name, fd->flags = state->flags; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": CREATE %s", req_callid (req), + "%"PRIu64": CREATE %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE, @@ -1418,14 +1458,14 @@ fuse_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->flags = fi->flags; ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": OPEN %s (fuse_loc_fill() failed)", + "%"PRIu64": OPEN %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); @@ -1438,7 +1478,7 @@ fuse_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fd->flags = fi->flags; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": OPEN %s", req_callid (req), + "%"PRIu64": OPEN %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPEN, @@ -1493,7 +1533,7 @@ fuse_readv (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, fuse_state_t *state = NULL; fd_t *fd = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; state->off = off; @@ -1501,7 +1541,7 @@ fuse_readv (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": READ (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", + "%"PRIu64": READ (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", req_callid (req), fd, size, off); FUSE_FOP (state, fuse_readv_cbk, GF_FOP_READ, @@ -1554,7 +1594,7 @@ fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf, struct iobref *iobref = NULL; struct iobuf *iobuf = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; state->off = off; fd = FI_TO_FD (fi); @@ -1563,10 +1603,18 @@ fuse_write (fuse_req_t req, fuse_ino_t ino, const char *buf, vector.iov_len = size; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": WRITE (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", + "%"PRIu64": WRITE (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", req_callid (req), fd, size, off); iobref = iobref_new (); + if (!iobref) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "%"PRIu64": WRITE iobref allocation failed", + req_callid (req)); + + free_state (state); + return; + } iobuf = ((fuse_private_t *) (state->this->private))->iobuf; iobref_add (iobref, iobuf); @@ -1584,12 +1632,12 @@ fuse_flush (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fuse_state_t *state = NULL; fd_t *fd = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); fd = FI_TO_FD (fi); state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FLUSH %p", req_callid (req), fd); + "%"PRIu64": FLUSH %p", req_callid (req), fd); FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, flush, fd); @@ -1603,11 +1651,11 @@ fuse_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { fuse_state_t *state = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->fd = FI_TO_FD (fi); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": RELEASE %p", req_callid (req), state->fd); + "%"PRIu64": RELEASE %p", req_callid (req), state->fd); fd_unref (state->fd); @@ -1625,12 +1673,12 @@ fuse_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, fuse_state_t *state = NULL; fd_t *fd = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); fd = FI_TO_FD (fi); state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": FSYNC %p", req_callid (req), fd); + "%"PRIu64": FSYNC %p", req_callid (req), fd); FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNC, fsync, fd, datasync); @@ -1646,12 +1694,12 @@ fuse_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fd_t *fd = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": OPENDIR %s (fuse_loc_fill() failed)", + "%"PRIu64": OPENDIR %s (fuse_loc_fill() failed)", req_callid (req), state->loc.path); fuse_reply_err (req, ENOENT); @@ -1663,7 +1711,7 @@ fuse_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": OPENDIR %s", req_callid (req), + "%"PRIu64": OPENDIR %s", req_callid (req), state->loc.path); FUSE_FOP (state, fuse_fd_cbk, GF_FOP_OPENDIR, @@ -1708,7 +1756,7 @@ fuse_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "%"PRId64": READDIR => -1 (%s)", frame->root->unique, strerror (ENOMEM)); - fuse_reply_err (req, -ENOMEM); + fuse_reply_err (req, ENOMEM); goto out; } @@ -1741,14 +1789,14 @@ fuse_readdir (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, fuse_state_t *state = NULL; fd_t *fd = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; state->off = off; fd = FI_TO_FD (fi); state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": READDIR (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", + "%"PRIu64": READDIR (%p, size=%"GF_PRI_SIZET", offset=%"PRId64")", req_callid (req), fd, size, off); FUSE_FOP (state, fuse_readdir_cbk, GF_FOP_READDIR, @@ -1761,11 +1809,11 @@ fuse_releasedir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { fuse_state_t *state = NULL; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->fd = FI_TO_FD (fi); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": RELEASEDIR %p", req_callid (req), state->fd); + "%"PRIu64": RELEASEDIR %p", req_callid (req), state->fd); fd_unref (state->fd); @@ -1786,7 +1834,7 @@ fuse_fsyncdir (fuse_req_t req, fuse_ino_t ino, int datasync, fd = FI_TO_FD (fi); - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->fd = fd; FUSE_FOP (state, fuse_err_cbk, GF_FOP_FSYNCDIR, @@ -1855,12 +1903,12 @@ fuse_statfs (fuse_req_t req, fuse_ino_t ino) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, 1, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": STATFS (fuse_loc_fill() fail)", + "%"PRIu64": STATFS (fuse_loc_fill() fail)", req_callid (req)); fuse_reply_err (req, ENOENT); @@ -1869,7 +1917,7 @@ fuse_statfs (fuse_req_t req, fuse_ino_t ino) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": STATFS", req_callid (req)); + "%"PRIu64": STATFS", req_callid (req)); FUSE_FOP (state, fuse_statfs_cbk, GF_FOP_STATFS, statfs, &state->loc); @@ -1891,13 +1939,13 @@ fuse_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name, } #endif - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": SETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": SETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), state->loc.path, (int64_t)ino, name); @@ -1907,6 +1955,14 @@ fuse_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name, } state->dict = get_new_dict (); + if (!state->dict) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "%"PRIu64": SETXATTR dict allocation failed", + req_callid (req)); + + free_state (state); + return; + } dict_value = memdup (value, size); dict_set (state->dict, (char *)name, @@ -1914,7 +1970,7 @@ fuse_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name, dict_ref (state->dict); gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": SETXATTR %s/%"PRId64" (%s)", req_callid (req), + "%"PRIu64": SETXATTR %s/%"PRId64" (%s)", req_callid (req), state->loc.path, (int64_t)ino, name); FUSE_FOP (state, fuse_err_cbk, GF_FOP_SETXATTR, @@ -2030,6 +2086,9 @@ fuse_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } else if (!strcmp (state->name, "user.glusterfs-booster-path")) { fuse_reply_xattr_buf (state, req, state->loc.path, strlen (state->loc.path) + 1); + } else if (!strcmp (state->name, "user.glusterfs-booster-mount")) { + fuse_reply_xattr_buf (state, req, priv->mount_point, + strlen(priv->mount_point) + 1); } else { fuse_reply_err (req, ENODATA); } /* if(value_data)...else */ @@ -2106,7 +2165,7 @@ fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) } #endif - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; state->name = strdup (name); @@ -2114,7 +2173,7 @@ fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": GETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": GETXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), state->loc.path, (int64_t)ino, name); fuse_reply_err (req, ENOENT); @@ -2123,7 +2182,7 @@ fuse_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": GETXATTR %s/%"PRId64" (%s)", req_callid (req), + "%"PRIu64": GETXATTR %s/%"PRId64" (%s)", req_callid (req), state->loc.path, (int64_t)ino, name); FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR, @@ -2139,13 +2198,13 @@ fuse_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->size = size; ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "%"PRId64": LISTXATTR %s/%"PRId64" (fuse_loc_fill() failed)", + "%"PRIu64": LISTXATTR %s/%"PRId64" (fuse_loc_fill() failed)", req_callid (req), state->loc.path, (int64_t)ino); fuse_reply_err (req, ENOENT); @@ -2154,7 +2213,7 @@ fuse_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": LISTXATTR %s/%"PRId64, req_callid (req), + "%"PRIu64": LISTXATTR %s/%"PRId64, req_callid (req), state->loc.path, (int64_t)ino); FUSE_FOP (state, fuse_xattr_cbk, GF_FOP_GETXATTR, @@ -2171,12 +2230,12 @@ fuse_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name) fuse_state_t *state = NULL; int32_t ret = -1; - state = state_from_req (req); + STATE_FROM_REQ (req, state); ret = fuse_loc_fill (&state->loc, state, ino, 0, NULL); if ((state->loc.inode == NULL) || (ret < 0)) { gf_log ("glusterfs-fuse", GF_LOG_DEBUG, - "%"PRId64": REMOVEXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", + "%"PRIu64": REMOVEXATTR %s/%"PRId64" (%s) (fuse_loc_fill() failed)", req_callid (req), state->loc.path, (int64_t)ino, name); fuse_reply_err (req, ENOENT); @@ -2185,7 +2244,7 @@ fuse_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name) } gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": REMOVEXATTR %s/%"PRId64" (%s)", req_callid (req), + "%"PRIu64": REMOVEXATTR %s/%"PRId64" (%s)", req_callid (req), state->loc.path, (int64_t)ino, name); FUSE_FOP (state, fuse_err_cbk, GF_FOP_REMOVEXATTR, @@ -2241,12 +2300,12 @@ fuse_getlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, fd_t *fd = NULL; fd = FI_TO_FD (fi); - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->req = req; state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": GETLK %p", req_callid (req), fd); + "%"PRIu64": GETLK %p", req_callid (req), fd); FUSE_FOP (state, fuse_getlk_cbk, GF_FOP_LK, lk, fd, F_GETLK, lock); @@ -2300,12 +2359,12 @@ fuse_setlk (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, fd_t *fd = NULL; fd = FI_TO_FD (fi); - state = state_from_req (req); + STATE_FROM_REQ (req, state); state->req = req; state->fd = fd; gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRId64": SETLK %p (sleep=%d)", req_callid (req), fd, + "%"PRIu64": SETLK %p (sleep=%d)", req_callid (req), fd, sleep); FUSE_FOP (state, fuse_setlk_cbk, GF_FOP_LK, @@ -2475,8 +2534,10 @@ fuse_thread_proc (void *data) gf_log ("glusterfs-fuse", GF_LOG_WARNING, "fuse_chan_receive() returned -1 (%d)", errno); } - if (errno == ENODEV) + if (errno == ENODEV) { + iobuf_unref (iobuf); break; + } continue; } @@ -2591,6 +2652,7 @@ init (xlator_t *this_xl) fuse_private_t *priv = NULL; struct stat stbuf = {0,}; struct fuse_args args = FUSE_ARGS_INIT (0, NULL); + int xl_name_allocated = 0; if (this_xl == NULL) return -1; @@ -2602,7 +2664,13 @@ init (xlator_t *this_xl) if (this_xl->name == NULL) { this_xl->name = strdup ("fuse"); - ERR_ABORT (this_xl->name); + if (!this_xl->name) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "Out of memory"); + + goto cleanup_exit; + } + xl_name_allocated = 1; } fsname = this_xl->ctx->cmd_args.volume_file; @@ -2653,12 +2721,22 @@ init (xlator_t *this_xl) #endif /* LINUX */ #endif /* ! DARWIN_OS */ - if (ret == -1) - ERR_ABORT (NULL); + if (ret == -1) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "Out of memory"); + + goto cleanup_exit; + } priv = CALLOC (1, sizeof (*priv)); - ERR_ABORT (priv); + if (!priv) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "Out of memory"); + + goto cleanup_exit; + } this_xl->private = (void *) priv; + priv->mount_point = NULL; /* get options from option dictionary */ ret = dict_get_str (options, ZR_MOUNTPOINT_OPT, &value_string); @@ -2694,7 +2772,12 @@ init (xlator_t *this_xl) goto cleanup_exit; } priv->mount_point = strdup (value_string); - ERR_ABORT (priv->mount_point); + if (!priv->mount_point) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "Out of memory"); + + goto cleanup_exit; + } ret = dict_get_double (options, "attribute-timeout", &priv->attribute_timeout); @@ -2720,6 +2803,14 @@ init (xlator_t *this_xl) &priv->strict_volfile_check); } + this_xl->itable = inode_table_new (0, this_xl); + if (!this_xl->itable) { + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "Out of memory"); + + goto cleanup_exit; + } + priv->ch = fuse_mount (priv->mount_point, &args); if (priv->ch == NULL) { if (errno == ENOTCONN) { @@ -2797,12 +2888,13 @@ init (xlator_t *this_xl) this_xl->ctx->top = this_xl; priv->first_call = 2; - this_xl->itable = inode_table_new (0, this_xl); return 0; umount_exit: fuse_unmount (priv->mount_point, priv->ch); cleanup_exit: + if (xl_name_allocated) + FREE (this_xl->name); fuse_opt_free_args (&args); FREE (fsname_opt); if (priv) diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in index 954032620..0bf8efd9d 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -16,7 +16,7 @@ # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA -function _init () +_init () { # log level definitions LOG_NONE=NONE; @@ -34,7 +34,7 @@ function _init () cmd_line=$(echo "@sbindir@/glusterfs"); } -function start_glusterfs () +start_glusterfs () { if [ -n "$log_level_str" ]; then case "$log_level_str" in @@ -115,7 +115,7 @@ function start_glusterfs () exec $cmd_line; } -function usage () +usage () { echo "Usage: mount.glusterfs <volumeserver>:<volumeid/volumeport> -o <options> <mountpoint> @@ -127,7 +127,7 @@ mount.glusterfs --version" } -function main () +main () { helper=$(echo "$@" | sed -n 's/.*\--[ ]*\([^ ]*\).*/\1/p'); diff --git a/xlators/performance/Makefile.am b/xlators/performance/Makefile.am index f7504bbe8..6b5facca5 100644 --- a/xlators/performance/Makefile.am +++ b/xlators/performance/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = write-behind read-ahead io-threads io-cache symlink-cache +SUBDIRS = write-behind read-ahead io-threads io-cache symlink-cache quick-read CLEANFILES = diff --git a/xlators/performance/quick-read/Makefile.am b/xlators/performance/quick-read/Makefile.am new file mode 100644 index 000000000..d471a3f92 --- /dev/null +++ b/xlators/performance/quick-read/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES = diff --git a/xlators/performance/quick-read/src/Makefile.am b/xlators/performance/quick-read/src/Makefile.am new file mode 100644 index 000000000..644f27e3f --- /dev/null +++ b/xlators/performance/quick-read/src/Makefile.am @@ -0,0 +1,14 @@ +xlator_LTLIBRARIES = quick-read.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/performance + +quick_read_la_LDFLAGS = -module -avoidversion + +quick_read_la_SOURCES = quick-read.c +quick_read_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +noinst_HEADERS = quick-read.h + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ + -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) + +CLEANFILES = diff --git a/xlators/performance/quick-read/src/quick-read.c b/xlators/performance/quick-read/src/quick-read.c new file mode 100644 index 000000000..7bc912e3d --- /dev/null +++ b/xlators/performance/quick-read/src/quick-read.c @@ -0,0 +1,2235 @@ +/* + Copyright (c) 2009-2010 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include "quick-read.h" + +int32_t +qr_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset); + + +static void +qr_loc_wipe (loc_t *loc) +{ + if (loc == NULL) { + goto out; + } + + if (loc->path) { + FREE (loc->path); + loc->path = NULL; + } + + if (loc->inode) { + inode_unref (loc->inode); + loc->inode = NULL; + } + + if (loc->parent) { + inode_unref (loc->parent); + loc->parent = NULL; + } + +out: + return; +} + + +static int32_t +qr_loc_fill (loc_t *loc, inode_t *inode, char *path) +{ + int32_t ret = -1; + char *parent = NULL; + + if ((loc == NULL) || (inode == NULL) || (path == NULL)) { + ret = -1; + errno = EINVAL; + goto out; + } + + loc->inode = inode_ref (inode); + loc->path = strdup (path); + loc->ino = inode->ino; + + parent = strdup (path); + if (parent == NULL) { + ret = -1; + goto out; + } + + parent = dirname (parent); + + loc->parent = inode_from_path (inode->table, parent); + if (loc->parent == NULL) { + ret = -1; + errno = EINVAL; + goto out; + } + + loc->name = strrchr (loc->path, '/'); + ret = 0; +out: + if (ret == -1) { + qr_loc_wipe (loc); + + } + + if (parent) { + FREE (parent); + } + + return ret; +} + + +void +qr_resume_pending_ops (qr_fd_ctx_t *qr_fd_ctx) +{ + struct list_head waiting_ops; + call_stub_t *stub = NULL, *tmp = NULL; + + if (qr_fd_ctx == NULL) { + goto out; + } + + INIT_LIST_HEAD (&waiting_ops); + + LOCK (&qr_fd_ctx->lock); + { + list_splice_init (&qr_fd_ctx->waiting_ops, + &waiting_ops); + } + UNLOCK (&qr_fd_ctx->lock); + + if (!list_empty (&waiting_ops)) { + list_for_each_entry_safe (stub, tmp, &waiting_ops, list) { + list_del_init (&stub->list); + call_resume (stub); + } + } + +out: + return; +} + + +static void +qr_fd_ctx_free (qr_fd_ctx_t *qr_fd_ctx) +{ + if (qr_fd_ctx == NULL) { + goto out; + } + + assert (list_empty (&qr_fd_ctx->waiting_ops)); + + FREE (qr_fd_ctx->path); + FREE (qr_fd_ctx); + +out: + return; +} + + +int32_t +qr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct stat *buf, dict_t *dict) +{ + data_t *content = NULL; + qr_file_t *qr_file = NULL; + uint64_t value = 0; + int ret = -1; + qr_conf_t *conf = NULL; + + if ((op_ret == -1) || (dict == NULL)) { + goto out; + } + + conf = this->private; + + content = dict_get (dict, GLUSTERFS_CONTENT_KEY); + if (content == NULL) { + goto out; + } + + if (buf->st_size > conf->max_file_size) { + goto out; + } + + if (S_ISDIR (buf->st_mode)) { + goto out; + } + + ret = inode_ctx_get (inode, this, &value); + if (ret == -1) { + qr_file = CALLOC (1, sizeof (*qr_file)); + if (qr_file == NULL) { + op_ret = -1; + op_errno = ENOMEM; + goto out; + } + + LOCK_INIT (&qr_file->lock); + inode_ctx_put (inode, this, (uint64_t)(long)qr_file); + } else { + qr_file = (qr_file_t *)(long)value; + if (qr_file == NULL) { + op_ret = -1; + op_errno = EINVAL; + goto out; + } + } + + LOCK (&qr_file->lock); + { + if (qr_file->xattr) { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + + qr_file->xattr = dict_ref (dict); + qr_file->stbuf = *buf; + gettimeofday (&qr_file->tv, NULL); + } + UNLOCK (&qr_file->lock); + +out: + STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict); + return 0; +} + + +int32_t +qr_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) +{ + qr_conf_t *conf = NULL; + dict_t *new_req_dict = NULL; + int32_t op_ret = -1, op_errno = -1; + data_t *content = NULL; + uint64_t requested_size = 0, size = 0; + + conf = this->private; + if (conf == NULL) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } + + if ((xattr_req == NULL) && (conf->max_file_size > 0)) { + new_req_dict = xattr_req = dict_new (); + if (xattr_req == NULL) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, "out of memory"); + goto unwind; + } + } + + if (xattr_req) { + content = dict_get (xattr_req, GLUSTERFS_CONTENT_KEY); + if (content) { + requested_size = data_to_uint64 (content); + } + } + + if (((conf->max_file_size > 0) && (content == NULL)) + || (conf->max_file_size != requested_size)) { + size = (conf->max_file_size > requested_size) ? + conf->max_file_size : requested_size; + + op_ret = dict_set (xattr_req, GLUSTERFS_CONTENT_KEY, + data_from_uint64 (size)); + if (op_ret < 0) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + } + + STACK_WIND (frame, qr_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xattr_req); + + if (new_req_dict) { + dict_unref (new_req_dict); + } + + return 0; + +unwind: + STACK_UNWIND (frame, op_ret, op_errno, NULL, NULL, NULL); + + if (new_req_dict) { + dict_unref (new_req_dict); + } + + return 0; +} + + +int32_t +qr_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd) +{ + uint64_t value = 0; + int32_t ret = -1; + struct list_head waiting_ops; + qr_local_t *local = NULL; + qr_file_t *qr_file = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + call_stub_t *stub = NULL, *tmp = NULL; + + local = frame->local; + INIT_LIST_HEAD (&waiting_ops); + + ret = fd_ctx_get (fd, this, &value); + if ((ret == -1) && (op_ret != -1)) { + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + if (value) { + qr_fd_ctx = (qr_fd_ctx_t *) (long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + qr_fd_ctx->open_in_transit = 0; + + if (op_ret == 0) { + qr_fd_ctx->opened = 1; + } + list_splice_init (&qr_fd_ctx->waiting_ops, + &waiting_ops); + } + UNLOCK (&qr_fd_ctx->lock); + + if (local && local->is_open + && ((local->open_flags & O_TRUNC) == O_TRUNC)) { + ret = inode_ctx_get (fd->inode, this, &value); + if (ret == 0) { + qr_file = (qr_file_t *)(long) value; + + if (qr_file) { + LOCK (&qr_file->lock); + { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + UNLOCK (&qr_file->lock); + } + } + } + + if (!list_empty (&waiting_ops)) { + list_for_each_entry_safe (stub, tmp, &waiting_ops, + list) { + list_del_init (&stub->list); + call_resume (stub); + } + } + } +out: + if (local && local->is_open) { + STACK_UNWIND (frame, op_ret, op_errno, fd); + } + + return 0; +} + + +int32_t +qr_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd) +{ + qr_file_t *qr_file = NULL; + int32_t ret = -1; + uint64_t filep = 0; + char content_cached = 0; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t op_ret = -1, op_errno = -1; + qr_local_t *local = NULL; + qr_conf_t *conf = NULL; + + conf = this->private; + + qr_fd_ctx = CALLOC (1, sizeof (*qr_fd_ctx)); + if (qr_fd_ctx == NULL) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, "out of memory"); + goto unwind; + } + + LOCK_INIT (&qr_fd_ctx->lock); + INIT_LIST_HEAD (&qr_fd_ctx->waiting_ops); + + qr_fd_ctx->path = strdup (loc->path); + qr_fd_ctx->flags = flags; + + ret = fd_ctx_set (fd, this, (uint64_t)(long)qr_fd_ctx); + if (ret == -1) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } + + local = CALLOC (1, sizeof (*local)); + if (local == NULL) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, "out of memory"); + goto unwind; + } + + local->is_open = 1; + local->open_flags = flags; + frame->local = local; + local = NULL; + + ret = inode_ctx_get (fd->inode, this, &filep); + if (ret == 0) { + qr_file = (qr_file_t *)(long) filep; + if (qr_file) { + LOCK (&qr_file->lock); + { + if (qr_file->xattr) { + content_cached = 1; + } + } + UNLOCK (&qr_file->lock); + } + } + + if (content_cached && ((flags & O_DIRECTORY) == O_DIRECTORY)) { + op_ret = -1; + op_errno = ENOTDIR; + qr_fd_ctx = NULL; + goto unwind; + } + + if (!content_cached || ((flags & O_WRONLY) == O_WRONLY) + || ((flags & O_TRUNC) == O_TRUNC)) { + LOCK (&qr_fd_ctx->lock); + { + /* + * we need not set this flag, since open is not yet + * unwounded. + */ + + qr_fd_ctx->open_in_transit = 1; + } + UNLOCK (&qr_fd_ctx->lock); + goto wind; + } else { + op_ret = 0; + op_errno = 0; + goto unwind; + } + +unwind: + if (op_ret == -1) { + if (qr_fd_ctx != NULL) { + qr_fd_ctx_free (qr_fd_ctx); + } + + if (local != NULL) { + FREE (local); + } + } + + STACK_UNWIND (frame, op_ret, op_errno, fd); + return 0; + +wind: + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, loc, flags, fd); + return 0; +} + + +static inline char +qr_time_elapsed (struct timeval *now, struct timeval *then) +{ + return now->tv_sec - then->tv_sec; +} + + +static inline char +qr_need_validation (qr_conf_t *conf, qr_file_t *file) +{ + struct timeval now = {0, }; + char need_validation = 0; + + gettimeofday (&now, NULL); + + if (qr_time_elapsed (&now, &file->tv) >= conf->cache_timeout) + need_validation = 1; + + return need_validation; +} + + +static int32_t +qr_validate_cache_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct stat *buf) +{ + qr_file_t *qr_file = NULL; + qr_local_t *local = NULL; + uint64_t value = 0; + int32_t ret = 0; + + if (op_ret == -1) { + goto unwind; + } + + local = frame->local; + if ((local == NULL) || ((local->fd) == NULL)) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } + + ret = inode_ctx_get (local->fd->inode, this, &value); + if (ret == -1) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } + + qr_file = (qr_file_t *)(long) value; + if (qr_file == NULL) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } + + LOCK (&qr_file->lock); + { + if (qr_file->stbuf.st_mtime != buf->st_mtime) { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + + gettimeofday (&qr_file->tv, NULL); + } + UNLOCK (&qr_file->lock); + + frame->local = NULL; + + call_resume (local->stub); + + FREE (local); + return 0; + +unwind: + /* this is actually unwind of readv */ + STACK_UNWIND (frame, op_ret, op_errno, NULL, -1, NULL, NULL); + return 0; +} + + +int32_t +qr_validate_cache_helper (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + STACK_WIND (frame, qr_validate_cache_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fstat, fd); + return 0; +} + + +int +qr_validate_cache (call_frame_t *frame, xlator_t *this, fd_t *fd, + call_stub_t *stub) +{ + int ret = -1; + int flags = 0; + uint64_t value = 0; + loc_t loc = {0, }; + char *path = NULL; + qr_local_t *local = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + call_stub_t *validate_stub = NULL; + char need_open = 0, can_wind = 0; + + local = CALLOC (1, sizeof (*local)); + if (local == NULL) { + goto out; + } + + local->fd = fd; + local->stub = stub; + frame->local = local; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + validate_stub = fop_fstat_stub (frame, + qr_validate_cache_helper, + fd); + if (validate_stub == NULL) { + ret = -1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&validate_stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + + if (ret == -1) { + goto out; + } + } else { + can_wind = 1; + } + + if (need_open) { + ret = qr_loc_fill (&loc, fd->inode, path); + if (ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, + &loc, flags, fd); + + qr_loc_wipe (&loc); + } else if (can_wind) { + STACK_WIND (frame, qr_validate_cache_cbk, + FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fstat, fd); + } + + ret = 0; +out: + return ret; +} + + +int32_t +qr_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 stat *stbuf, struct iobref *iobref) +{ + STACK_UNWIND (frame, op_ret, op_errno, vector, count, stbuf, iobref); + return 0; +} + + +int32_t +qr_readv_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset) +{ + STACK_WIND (frame, qr_readv_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->readv, fd, size, offset); + return 0; +} + + +int32_t +qr_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset) +{ + qr_file_t *file = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + uint64_t value = 0; + int count = -1, flags = 0, i = 0; + char content_cached = 0, need_validation = 0; + char need_open = 0, can_wind = 0, need_unwind = 0; + struct iobuf *iobuf = NULL; + struct iobref *iobref = NULL; + struct stat stbuf = {0, }; + data_t *content = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + call_stub_t *stub = NULL; + loc_t loc = {0, }; + qr_conf_t *conf = NULL; + struct iovec *vector = NULL; + char *path = NULL; + glusterfs_ctx_t *ctx = NULL; + off_t start = 0, end = 0; + size_t len = 0; + + op_ret = 0; + conf = this->private; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + ret = inode_ctx_get (fd->inode, this, &value); + if (ret == 0) { + file = (qr_file_t *)(long)value; + if (file) { + LOCK (&file->lock); + { + if (file->xattr){ + if (qr_need_validation (conf,file)) { + need_validation = 1; + goto unlock; + } + + content = dict_get (file->xattr, + GLUSTERFS_CONTENT_KEY); + + content_cached = 1; + if (offset > content->len) { + op_ret = 0; + end = content->len; + } else { + if ((offset + size) + > content->len) { + op_ret = content->len - offset; + end = content->len; + } else { + op_ret = size; + end = offset + size; + } + } + + ctx = glusterfs_ctx_get (); + count = (op_ret / ctx->page_size) + 1; + vector = CALLOC (count, + sizeof (*vector)); + if (vector == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + goto unlock; + } + + iobref = iobref_new (); + if (iobref == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + goto unlock; + } + + for (i = 0; i < count; i++) { + iobuf = iobuf_get (this->ctx->iobuf_pool); + if (iobuf == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + goto unlock; + } + + start = offset + ctx->page_size * i; + if (start > end) { + len = 0; + } else { + len = (ctx->page_size + > (end - start)) + ? (end - start) + : ctx->page_size; + + memcpy (iobuf->ptr, + content->data + start, + len); + } + + iobref_add (iobref, iobuf); + iobuf_unref (iobuf); + + vector[i].iov_base = iobuf->ptr; + vector[i].iov_len = len; + } + + stbuf = file->stbuf; + } + } + unlock: + UNLOCK (&file->lock); + } + } + +out: + if (content_cached || need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, vector, count, &stbuf, + iobref); + + } else if (need_validation) { + stub = fop_readv_stub (frame, qr_readv, fd, size, offset); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + goto out; + } + + op_ret = qr_validate_cache (frame, this, fd, stub); + if (op_ret == -1) { + need_unwind = 1; + op_errno = errno; + call_stub_destroy (stub); + goto out; + } + } else { + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_readv_stub (frame, + qr_readv_helper, + fd, size, + offset); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto fdctx_unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + fdctx_unlock: + UNLOCK (&qr_fd_ctx->lock); + + if (op_ret == -1) { + need_unwind = 1; + goto out; + } + } else { + can_wind = 1; + } + + if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, + &loc, flags, fd); + + qr_loc_wipe (&loc); + } else if (can_wind) { + STACK_WIND (frame, qr_readv_cbk, + FIRST_CHILD (this), + FIRST_CHILD (this)->fops->readv, fd, size, + offset); + } + + } + + if (vector) { + FREE (vector); + } + + if (iobref) { + iobref_unref (iobref); + } + + return 0; +} + + +int32_t +qr_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct stat *stbuf) +{ + STACK_UNWIND (frame, op_ret, op_errno, stbuf); + return 0; +} + + +int32_t +qr_writev_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, + struct iobref *iobref) +{ + STACK_WIND (frame, qr_writev_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->writev, fd, vector, count, off, + iobref); + return 0; +} + + +int32_t +qr_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, + int32_t count, off_t off, struct iobref *iobref) +{ + uint64_t value = 0; + int flags = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_file_t *qr_file = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t op_ret = -1, op_errno = -1, ret = -1; + char can_wind = 0, need_unwind = 0, need_open = 0; + + ret = fd_ctx_get (fd, this, &value); + + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + ret = inode_ctx_get (fd->inode, this, &value); + if (ret == 0) { + qr_file = (qr_file_t *)(long)value; + } + + if (qr_file) { + LOCK (&qr_file->lock); + { + if (qr_file->xattr) { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + } + UNLOCK (&qr_file->lock); + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_writev_stub (frame, qr_writev_helper, + fd, vector, count, off, + iobref); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_writev_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->writev, fd, vector, count, + off, iobref); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + + +int32_t +qr_fstat_helper (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + STACK_WIND (frame, qr_fstat_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fstat, fd); + return 0; +} + + +int32_t +qr_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + qr_fd_ctx_t *qr_fd_ctx = NULL; + char need_open = 0, can_wind = 0, need_unwind = 0; + uint64_t value = 0; + int32_t ret = -1, op_ret = -1, op_errno = -1; + call_stub_t *stub = NULL; + loc_t loc = {0, }; + char *path = NULL; + int flags = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fstat_stub (frame, qr_fstat_helper, + fd); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_fstat_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fstat, fd); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +static int32_t +qr_fchown_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + + +int32_t +qr_fchown_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, uid_t uid, + gid_t gid) +{ + STACK_WIND (frame, qr_fchown_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fchown, fd, uid, gid); + return 0; +} + + +int32_t +qr_fchown (call_frame_t *frame, xlator_t *this, fd_t *fd, uid_t uid, gid_t gid) +{ + uint64_t value = 0; + int flags = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fchown_stub (frame, qr_fchown_helper, + fd, uid, gid); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_fchown_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fchown, fd, uid, gid); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_fchmod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + + +int32_t +qr_fchmod_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, mode_t mode) +{ + STACK_WIND(frame, qr_fchmod_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fchmod, fd, mode); + return 0; +} + + +int32_t +qr_fchmod (call_frame_t *frame, xlator_t *this, fd_t *fd, mode_t mode) +{ + uint64_t value = 0; + int flags = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fchmod_stub (frame, qr_fchmod_helper, + fd, mode); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_fchmod_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fchmod, fd, mode); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +qr_fsetxattr_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags) +{ + STACK_WIND (frame, qr_fsetxattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetxattr, fd, dict, flags); + return 0; +} + + +int32_t +qr_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags) +{ + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + int open_flags = 0; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + open_flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fsetxattr_stub (frame, + qr_fsetxattr_helper, + fd, dict, flags); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } else if (can_wind) { + STACK_WIND (frame, qr_fsetxattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetxattr, fd, dict, + flags); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, open_flags, + fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict) +{ + STACK_UNWIND (frame, op_ret, op_errno, dict); + return 0; +} + + +int32_t +qr_fgetxattr_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name) +{ + STACK_WIND (frame, qr_fgetxattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fgetxattr, fd, name); + return 0; +} + + +int32_t +qr_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name) +{ + int flags = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + /* + * FIXME: Can quick-read use the extended attributes stored in the + * cache? this needs to be discussed. + */ + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fgetxattr_stub (frame, + qr_fgetxattr_helper, + fd, name); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_fgetxattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fgetxattr, fd, name); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +qr_flush_helper (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + STACK_WIND (frame, qr_flush_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->flush, fd); + return 0; +} + + +int32_t +qr_flush (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + uint64_t value = 0; + call_stub_t *stub = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + if (qr_fd_ctx->opened) { + can_wind = 1; + } else if (qr_fd_ctx->open_in_transit) { + stub = fop_flush_stub (frame, qr_flush_helper, + fd); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } else { + op_ret = 0; + need_unwind = 1; + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + op_ret = 0; + need_unwind = 1; + } + + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } else if (can_wind) { + STACK_WIND (frame, qr_flush_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->flush, fd); + } + + return 0; +} + + +int32_t +qr_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +qr_fentrylk_helper (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type) +{ + STACK_WIND(frame, qr_fentrylk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, volume, fd, basename, + cmd, type); + return 0; +} + + +int32_t +qr_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, + const char *basename, entrylk_cmd cmd, entrylk_type type) +{ + int flags = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fentrylk_stub (frame, + qr_fentrylk_helper, + volume, fd, basename, + cmd, type); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } else if (can_wind) { + STACK_WIND (frame, qr_fentrylk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, volume, fd, + basename, cmd, type); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno) + +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +qr_finodelk_helper (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, int32_t cmd, struct flock *lock) +{ + STACK_WIND (frame, qr_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, volume, fd, cmd, lock); + return 0; +} + + +int32_t +qr_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, + int32_t cmd, struct flock *lock) +{ + int flags = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_finodelk_stub (frame, + qr_finodelk_helper, + volume, fd, cmd, + lock); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } else if (can_wind) { + STACK_WIND (frame, qr_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, volume, fd, + cmd, lock); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +qr_fsync_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ + STACK_WIND (frame, qr_fsync_cbk, FIRST_CHILD (this), + FIRST_CHILD(this)->fops->fsync, fd, flags); + return 0; +} + +int32_t +qr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + int open_flags = 0; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + open_flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_fsync_stub (frame, qr_fsync_helper, + fd, flags); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } else if (can_wind) { + STACK_WIND (frame, qr_fsync_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsync, fd, flags); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, open_flags, + fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct stat *buf) +{ + int32_t ret = 0; + uint64_t value = 0; + qr_file_t *qr_file = NULL; + qr_local_t *local = NULL; + + if (op_ret == -1) { + goto out; + } + + local = frame->local; + if ((local == NULL) || (local->fd == NULL) + || (local->fd->inode == NULL)) { + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + ret = inode_ctx_get (local->fd->inode, this, &value); + if (ret == 0) { + qr_file = (qr_file_t *)(long) value; + + if (qr_file) { + LOCK (&qr_file->lock); + { + if (qr_file->stbuf.st_size != buf->st_size) { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + } + UNLOCK (&qr_file->lock); + } + } + +out: + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + + +int32_t +qr_ftruncate_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset) +{ + STACK_WIND (frame, qr_ftruncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset); + return 0; +} + + +int32_t +qr_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ + int flags = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_local_t *local = NULL; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + local = CALLOC (1, sizeof (*local)); + if (local == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + goto out; + } + + local->fd = fd; + frame->local = local; + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_ftruncate_stub (frame, + qr_ftruncate_helper, + fd, offset); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_ftruncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct flock *lock) +{ + STACK_UNWIND (frame, op_ret, op_errno, lock); + return 0; +} + + +int32_t +qr_lk_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct flock *lock) +{ + STACK_WIND (frame, qr_lk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, fd, cmd, lock); + + return 0; +} + + +int32_t +qr_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct flock *lock) +{ + int flags = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + char *path = NULL; + loc_t loc = {0, }; + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = -1, op_ret = -1, op_errno = -1; + char need_open = 0, can_wind = 0, need_unwind = 0; + + ret = fd_ctx_get (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long)value; + } + + if (qr_fd_ctx) { + LOCK (&qr_fd_ctx->lock); + { + path = qr_fd_ctx->path; + flags = qr_fd_ctx->flags; + + if (!(qr_fd_ctx->opened + || qr_fd_ctx->open_in_transit)) { + need_open = 1; + qr_fd_ctx->open_in_transit = 1; + } + + if (qr_fd_ctx->opened) { + can_wind = 1; + } else { + stub = fop_lk_stub (frame, qr_lk_helper, fd, + cmd, lock); + if (stub == NULL) { + op_ret = -1; + op_errno = ENOMEM; + need_unwind = 1; + qr_fd_ctx->open_in_transit = 0; + goto unlock; + } + + list_add_tail (&stub->list, + &qr_fd_ctx->waiting_ops); + } + } + unlock: + UNLOCK (&qr_fd_ctx->lock); + } else { + can_wind = 1; + } + +out: + if (need_unwind) { + STACK_UNWIND (frame, op_ret, op_errno, NULL); + } else if (can_wind) { + STACK_WIND (frame, qr_lk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, fd, cmd, lock); + } else if (need_open) { + op_ret = qr_loc_fill (&loc, fd->inode, path); + if (op_ret == -1) { + qr_resume_pending_ops (qr_fd_ctx); + goto out; + } + + STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, &loc, flags, fd); + + qr_loc_wipe (&loc); + } + + return 0; +} + + +int32_t +qr_release (xlator_t *this, fd_t *fd) +{ + qr_fd_ctx_t *qr_fd_ctx = NULL; + int32_t ret = 0; + uint64_t value = 0; + + ret = fd_ctx_del (fd, this, &value); + if (ret == 0) { + qr_fd_ctx = (qr_fd_ctx_t *)(long) value; + if (qr_fd_ctx) { + qr_fd_ctx_free (qr_fd_ctx); + } + } + + return 0; +} + + +int32_t +qr_forget (xlator_t *this, inode_t *inode) +{ + qr_file_t *qr_file = NULL; + uint64_t value = 0; + int32_t ret = -1; + + ret = inode_ctx_del (inode, this, &value); + if (ret == 0) { + qr_file = (qr_file_t *)(long) value; + if (qr_file) { + LOCK (&qr_file->lock); + { + if (qr_file->xattr) { + dict_unref (qr_file->xattr); + qr_file->xattr = NULL; + } + } + UNLOCK (&qr_file->lock); + } + + FREE (qr_file); + } + + return 0; +} + + +int32_t +init (xlator_t *this) +{ + char *str = NULL; + int32_t ret = -1; + qr_conf_t *conf = NULL; + + if (!this->children || this->children->next) { + gf_log (this->name, GF_LOG_ERROR, + "FATAL: volume (%s) not configured with exactly one " + "child", this->name); + return -1; + } + + if (!this->parents) { + gf_log (this->name, GF_LOG_WARNING, + "dangling volume. check volfile "); + } + + conf = CALLOC (1, sizeof (*conf)); + if (conf == NULL) { + gf_log (this->name, GF_LOG_ERROR, + "out of memory"); + ret = -1; + goto out; + } + + ret = dict_get_str (this->options, "max-file-size", + &str); + if (ret == 0) { + ret = gf_string2bytesize (str, &conf->max_file_size); + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, + "invalid number format \"%s\" of \"option " + "max-file-size\"", + str); + ret = -1; + goto out; + } + } + + conf->cache_timeout = -1; + ret = dict_get_str (this->options, "cache-timeout", &str); + if (ret == 0) { + ret = gf_string2uint_base10 (str, + (unsigned int *)&conf->cache_timeout); + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, + "invalid cache-timeout value %s", str); + ret = -1; + goto out; + } + } + + this->private = conf; +out: + if ((ret == -1) && conf) { + FREE (conf); + } + + return ret; +} + + +void +fini (xlator_t *this) +{ + return; +} + + +struct xlator_fops fops = { + .lookup = qr_lookup, + .open = qr_open, + .readv = qr_readv, + .writev = qr_writev, + .fstat = qr_fstat, + .fchown = qr_fchown, + .fchmod = qr_fchmod, + .fsetxattr = qr_fsetxattr, + .fgetxattr = qr_fgetxattr, + .flush = qr_flush, + .fentrylk = qr_fentrylk, + .finodelk = qr_finodelk, + .fsync = qr_fsync, + .ftruncate = qr_ftruncate, + .lk = qr_lk, +}; + + +struct xlator_mops mops = { +}; + + +struct xlator_cbks cbks = { + .forget = qr_forget, + .release = qr_release, +}; + +struct volume_options options[] = { + { .key = {"cache-timeout"}, + .type = GF_OPTION_TYPE_INT, + .min = 1, + .max = 60 + }, + { .key = {"max-file-size"}, + .type = GF_OPTION_TYPE_SIZET, + .min = 0, + .max = 1 * GF_UNIT_MB + }, +}; diff --git a/xlators/performance/quick-read/src/quick-read.h b/xlators/performance/quick-read/src/quick-read.h new file mode 100644 index 000000000..32bebac48 --- /dev/null +++ b/xlators/performance/quick-read/src/quick-read.h @@ -0,0 +1,78 @@ +/* + Copyright (c) 2009-2010 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef __QUICK_READ_H +#define __QUICK_READ_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" +#include "logging.h" +#include "dict.h" +#include "xlator.h" +#include "list.h" +#include "compat.h" +#include "compat-errno.h" +#include "common-utils.h" +#include "call-stub.h" +#include "defaults.h" +#include <libgen.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define GLUSTERFS_CONTENT_KEY "glusterfs.content" + +struct qr_fd_ctx { + char opened; + char open_in_transit; + char *path; + int flags; + struct list_head waiting_ops; + gf_lock_t lock; +}; +typedef struct qr_fd_ctx qr_fd_ctx_t; + +struct qr_local { + char is_open; + fd_t *fd; + int open_flags; + call_stub_t *stub; +}; +typedef struct qr_local qr_local_t; + +struct qr_file { + dict_t *xattr; + struct stat stbuf; + struct timeval tv; + gf_lock_t lock; +}; +typedef struct qr_file qr_file_t; + +struct qr_conf { + uint64_t max_file_size; + int32_t cache_timeout; +}; +typedef struct qr_conf qr_conf_t; + +#endif /* #ifndef __QUICK_READ_H */ diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c index f0dd2e88e..7862ea47b 100644 --- a/xlators/protocol/server/src/server-protocol.c +++ b/xlators/protocol/server/src/server-protocol.c @@ -5627,8 +5627,7 @@ server_inodelk (call_frame_t *frame, xlator_t *bound_xl, state->volume, &state->loc, state->cmd, &state->flock); - if ((state->loc.parent == NULL) || - (state->loc.inode == NULL)) { + if (state->loc.inode == NULL) { do_path_lookup (inodelk_stub, &(state->loc)); } else { call_resume (inodelk_stub); @@ -5786,8 +5785,7 @@ server_entrylk (call_frame_t *frame, xlator_t *bound_xl, state->volume, &state->loc, state->name, state->cmd, state->type); - if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) || - (state->loc.inode == NULL)) { + if (state->loc.inode == NULL) { do_path_lookup (entrylk_stub, &(state->loc)); } else { call_resume (entrylk_stub); |