summaryrefslogtreecommitdiffstats
path: root/COPYING-LGPLV3
diff options
context:
space:
mode:
Diffstat (limited to 'COPYING-LGPLV3')
0 files changed, 0 insertions, 0 deletions
free (qr_fd_ctx_t *qr_fd_ctx) { GF_VALIDATE_OR_GOTO ("quick-read", qr_fd_ctx, out); GF_ASSERT (list_empty (&qr_fd_ctx->waiting_ops)); GF_FREE (qr_fd_ctx->path); GF_FREE (qr_fd_ctx); out: return; } static inline uint32_t is_match (const char *path, const char *pattern) { int32_t ret = 0; uint32_t match = 0; GF_VALIDATE_OR_GOTO ("quick-read", path, out); GF_VALIDATE_OR_GOTO ("quick-read", pattern, out); ret = fnmatch (pattern, path, FNM_NOESCAPE); match = (ret == 0); out: return match; } uint32_t qr_get_priority (qr_conf_t *conf, const char *path) { uint32_t priority = 0; struct qr_priority *curr = NULL; GF_VALIDATE_OR_GOTO ("quick-read", conf, out); GF_VALIDATE_OR_GOTO ("quick-read", path, out); list_for_each_entry (curr, &conf->priority_list, list) { if (is_match (path, curr->pattern)) priority = curr->priority; } out: return priority; } /* To be called with this-priv->table.lock held */ qr_inode_t * __qr_inode_alloc (xlator_t *this, char *path, inode_t *inode) { qr_inode_t *qr_inode = NULL; qr_private_t *priv = NULL; int priority = 0; GF_VALIDATE_OR_GOTO ("quick-read", this, out); GF_VALIDATE_OR_GOTO (this->name, path, out); GF_VALIDATE_OR_GOTO (this->name, inode, out); priv = this->private; GF_VALIDATE_OR_GOTO (this->name, priv, out); qr_inode = GF_CALLOC (1, sizeof (*qr_inode), gf_qr_mt_qr_inode_t); if (qr_inode == NULL) { goto out; } INIT_LIST_HEAD (&qr_inode->lru); priority = qr_get_priority (&priv->conf, path); list_add_tail (&qr_inode->lru, &priv->table.lru[priority]); qr_inode->inode = inode; qr_inode->priority = priority; out: return qr_inode; } /* To be called with qr_inode->table->lock held */ void __qr_inode_free (qr_inode_t *qr_inode) { GF_VALIDATE_OR_GOTO ("quick-read", qr_inode, out); if (qr_inode->xattr) { dict_unref (qr_inode->xattr); } list_del (&qr_inode->lru); GF_FREE (qr_inode); out: return; } /* To be called with priv->table.lock held */ void __qr_cache_prune (xlator_t *this) { qr_private_t *priv = NULL; qr_conf_t *conf = NULL; qr_inode_table_t *table = NULL; qr_inode_t *curr = NULL, *next = NULL; int32_t index = 0; uint64_t size_to_prune = 0; uint64_t size_pruned = 0; GF_VALIDATE_OR_GOTO ("quick-read", this, out); priv = this->private; GF_VALIDATE_OR_GOTO (this->name, priv, out); table = &priv->table; conf = &priv->conf; size_to_prune = table->cache_used - conf->cache_size; for (index=0; index < conf->max_pri; index++) { list_for_each_entry_safe (curr, next, &table->lru[index], lru) { size_pruned += curr->stbuf.ia_size; inode_ctx_del (curr->inode, this, NULL); __qr_inode_free (curr); if (size_pruned >= size_to_prune) goto done; } } done: table->cache_used -= size_pruned; out: return; } /* To be called with table->lock held */ inline char __qr_need_cache_prune (qr_conf_t *conf, qr_inode_table_t *table) { char need_prune = 0; GF_VALIDATE_OR_GOTO ("quick-read", conf, out); GF_VALIDATE_OR_GOTO ("quick-read", table, out); need_prune = (table->cache_used > conf->cache_size); out: return need_prune; } 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 iatt *buf, dict_t *dict, struct iatt *postparent) { data_t *content = NULL; qr_inode_t *qr_inode = NULL; uint64_t value = 0; int ret = -1; qr_conf_t *conf = NULL; qr_inode_table_t *table = NULL; qr_private_t *priv = NULL; qr_local_t *local = NULL; GF_ASSERT (frame); if ((op_ret == -1) || (dict == NULL)) { goto out; } if ((this == NULL) || (this->private == NULL)) { gf_log (frame->this->name, GF_LOG_WARNING, (this == NULL) ? "xlator object (this) is NULL" : "quick-read configuration is not found"); op_ret = -1; op_errno = EINVAL; goto out; } priv = this->private; conf = &priv->conf; table = &priv->table; local = frame->local; if (buf->ia_size > conf->max_file_size) { goto out; } if (IA_ISDIR (buf->ia_type)) { goto out; } if (inode == NULL) { op_ret = -1; op_errno = EINVAL; gf_log (this->name, GF_LOG_WARNING, "lookup returned a NULL inode"); goto out; } content = dict_get (dict, GF_CONTENT_KEY); if (content == NULL) { goto out; } LOCK (&table->lock); { ret = inode_ctx_get (inode, this, &value); if (ret == -1) { qr_inode = __qr_inode_alloc (this, local->path, inode); if (qr_inode == NULL) { op_ret = -1; op_errno = ENOMEM; goto unlock; } ret = inode_ctx_put (inode, this, (uint64_t)(long)qr_inode); if (ret == -1) { __qr_inode_free (qr_inode); qr_inode = NULL; op_ret = -1; op_errno = EINVAL; gf_log (this->name, GF_LOG_WARNING, "cannot set quick-read context in " "inode (ino:%"PRId64" gfid:%s)", inode->ino, inode->gfid); goto unlock; } } else { qr_inode = (qr_inode_t *)(long)value; if (qr_inode == NULL) { op_ret = -1; op_errno = EINVAL; gf_log (this->name, GF_LOG_WARNING, "cannot find quick-read context in " "inode (ino:%"PRId64" gfid:%s)", inode->ino, uuid_utoa (inode->gfid)); goto unlock; } } if (qr_inode->xattr) { dict_unref (qr_inode->xattr); qr_inode->xattr = NULL; table->cache_used -= qr_inode->stbuf.ia_size; } qr_inode->xattr = dict_ref (dict); qr_inode->stbuf = *buf; table->cache_used += buf->ia_size; gettimeofday (&qr_inode->tv, NULL); if (__qr_need_cache_prune (conf, table)) { __qr_cache_prune (this); } } unlock: UNLOCK (&table->lock); out: /* * FIXME: content size in dict can be greater than the size application * requested for. Applications need to be careful till this is fixed. */ QR_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, buf, dict, postparent); 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 = EINVAL; data_t *content = NULL; uint64_t requested_size = 0, size = 0, value = 0; char cached = 0; qr_inode_t *qr_inode = NULL; qr_private_t *priv = NULL; qr_inode_table_t *table = NULL; qr_local_t *local = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, loc, unwind); priv = this->private; GF_VALIDATE_OR_GOTO (frame->this->name, priv, unwind); conf = &priv->conf; if (conf == NULL) { op_ret = -1; op_errno = EINVAL; goto unwind; } table = &priv->table; local = GF_CALLOC (1, sizeof (*local), gf_qr_mt_qr_local_t); GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, op_errno, ENOMEM); frame->local = local; local->path = gf_strdup (loc->path); GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, op_errno, ENOMEM); LOCK (&table->lock); { op_ret = inode_ctx_get (loc->inode, this, &value); if (op_ret == 0) { qr_inode = (qr_inode_t *)(long)value; if (qr_inode != NULL) { if (qr_inode->xattr) { cached = 1; } } } } UNLOCK (&table->lock); 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; goto unwind; } } if (!cached) { if (xattr_req) { content = dict_get (xattr_req, GF_CONTENT_KEY); if (content) { requested_size = data_to_uint64 (content); } } if ((conf->max_file_size > 0) && (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, GF_CONTENT_KEY, data_from_uint64 (size)); if (op_ret < 0) { op_ret = -1; op_errno = ENOMEM; gf_log (this->name, GF_LOG_WARNING, "cannot set key in request dict to " "request file " "content during lookup cbk"); 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: QR_STACK_UNWIND (lookup, frame, op_ret, op_errno, NULL, 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; qr_local_t *local = NULL; qr_inode_t *qr_inode = NULL; qr_fd_ctx_t *qr_fd_ctx = NULL; call_stub_t *stub = NULL, *tmp = NULL; char is_open = 0; qr_private_t *priv = NULL; qr_inode_table_t *table = NULL; struct list_head waiting_ops; GF_ASSERT (frame); priv = this->private; table = &priv->table; local = frame->local; if (local != NULL) { is_open = local->is_open; } INIT_LIST_HEAD (&waiting_ops); ret = fd_ctx_get (fd, this, &value); if ((ret == -1) && (op_ret != -1)) { op_ret = -1; op_errno = EINVAL; gf_log (this->name, GF_LOG_WARNING, "cannot find quick-read context in fd (%p) opened on " "inode (ino:%"PRId64" gfid: %s", fd, fd->inode->ino, uuid_utoa (fd->inode->gfid)); 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)) { LOCK (&table->lock); { ret = inode_ctx_del (fd->inode, this, &value); if (ret == 0) { qr_inode = (qr_inode_t *)(long) value; if (qr_inode != NULL) { __qr_inode_free (qr_inode); } } } UNLOCK (&table->lock); } if (!list_empty (&waiting_ops)) { list_for_each_entry_safe (stub, tmp, &waiting_ops, list) { list_del_init (&stub->list); if (op_ret < 0) { qr_local_t *local = NULL; local = stub->frame->local; local->op_ret = op_ret; local->op_errno = op_errno; } call_resume (stub); } } } out: if (is_open) { QR_STACK_UNWIND (open, frame, op_ret, op_errno, fd); } else { STACK_DESTROY (frame->root); } return 0; } int32_t qr_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, fd_t *fd, int32_t wbflags) { qr_inode_t *qr_inode = NULL; int32_t ret = -1; uint64_t filep = 0; char content_cached = 0; qr_fd_ctx_t *qr_fd_ctx = NULL, *tmp_fd_ctx = NULL; int32_t op_ret = -1, op_errno = EINVAL; qr_local_t *local = NULL; qr_private_t *priv = NULL; qr_inode_table_t *table = NULL; GF_ASSERT (frame); GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, this->private, unwind); GF_VALIDATE_OR_GOTO (frame->this->name, fd, unwind); priv = this->private; table = &priv->table; tmp_fd_ctx = qr_fd_ctx = GF_CALLOC (1, sizeof (*qr_fd_ctx), gf_qr_mt_qr_fd_ctx_t); if (qr_fd_ctx == NULL) { op_ret = -1; op_errno = ENOMEM; goto unwind; } LOCK_INIT (&qr_fd_ctx->lock); INIT_LIST_HEAD (&qr_fd_ctx->waiting_ops); qr_fd_ctx->path = gf_strdup (loc->path); if (qr_fd_ctx->path == NULL) { op_ret = -1; op_errno = ENOMEM; goto unwind; } qr_fd_ctx->flags = flags; qr_fd_ctx->wbflags = wbflags; ret = fd_ctx_set (fd, this, (uint64_t)(long)qr_fd_ctx); if (ret == -1) { op_ret = -1; op_errno = EINVAL; gf_log (this->name, GF_LOG_WARNING, "cannot set quick-read context in " "fd (%p) opened on inode (ino:%"PRId64" gfid:%s)", fd, fd->inode->ino, uuid_utoa (fd->inode->gfid)); goto unwind; } tmp_fd_ctx = NULL; local = GF_CALLOC (1, sizeof (*local), gf_qr_mt_qr_local_t); if (local == NULL) { op_ret = -1; op_errno = ENOMEM; goto unwind; } local->is_open = 1; local->open_flags = flags; frame->local = local; LOCK (&table->lock); { ret = inode_ctx_get (fd->inode, this, &filep); if (ret == 0) { qr_inode = (qr_inode_t *)(long) filep; if (qr_inode) { if (qr_inode->xattr) { content_cached = 1; } } } } UNLOCK (&table->lock); if (content_cached && ((flags & O_DIRECTORY) == O_DIRECTORY)) { op_ret = -1; op_errno = ENOTDIR; gf_log (this->name, GF_LOG_WARNING, "open with O_DIRECTORY flag received on non-directory"); goto unwind; } if (!content_cached || ((flags & O_ACCMODE) == O_WRONLY) || ((flags & O_TRUNC) == O_TRUNC) || ((flags & O_DIRECT) == O_DIRECT) || ((wbflags & GF_OPEN_NOWB) != 0)) { LOCK (&qr_fd_ctx->lock); { /* * we really need not set this flag, since open is * not yet unwounded. */ qr_fd_ctx->open_in_transit = 1; if (((flags & O_DIRECT) == O_DIRECT) || ((wbflags & GF_OPEN_NOWB)) != 0) { qr_fd_ctx->disabled = 1; } } UNLOCK (&qr_fd_ctx->lock); goto wind; } else { op_ret = 0; op_errno = 0; goto unwind; } unwind: if (tmp_fd_ctx != NULL) { qr_fd_ctx_free (tmp_fd_ctx); } QR_STACK_UNWIND (open, 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, wbflags); return 0; } static inline time_t qr_time_elapsed (struct timeval *no