diff options
Diffstat (limited to 'xlators/encryption/crypt/src/crypt.c')
-rw-r--r-- | xlators/encryption/crypt/src/crypt.c | 7571 |
1 files changed, 3476 insertions, 4095 deletions
diff --git a/xlators/encryption/crypt/src/crypt.c b/xlators/encryption/crypt/src/crypt.c index 93d64c82a9e..02c4028c087 100644 --- a/xlators/encryption/crypt/src/crypt.c +++ b/xlators/encryption/crypt/src/crypt.c @@ -18,231 +18,242 @@ #include "crypt-common.h" #include "crypt.h" -static void init_inode_info_head(struct crypt_inode_info *info, fd_t *fd); -static int32_t init_inode_info_tail(struct crypt_inode_info *info, - struct master_cipher_info *master); -static int32_t prepare_for_submit_hole(call_frame_t *frame, xlator_t *this, - uint64_t from, off_t size); -static int32_t load_file_size(call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno, - dict_t *dict, dict_t *xdata); -static void do_ordered_submit(call_frame_t *frame, xlator_t *this, - atom_data_type dtype); -static void do_parallel_submit(call_frame_t *frame, xlator_t *this, - atom_data_type dtype); -static void put_one_call_open(call_frame_t *frame); -static void put_one_call_readv(call_frame_t *frame, xlator_t *this); -static void put_one_call_writev(call_frame_t *frame, xlator_t *this); -static void put_one_call_ftruncate(call_frame_t *frame, xlator_t *this); -static void free_avec(struct iovec *avec, char **pool, int blocks_in_pool); -static void free_avec_data(crypt_local_t *local); -static void free_avec_hole(crypt_local_t *local); - -static crypt_local_t *crypt_alloc_local(call_frame_t *frame, xlator_t *this, - glusterfs_fop_t fop) -{ - crypt_local_t *local = NULL; - - local = GF_CALLOC (1, sizeof (crypt_local_t), gf_crypt_mt_local); - if (!local) { - gf_log(this->name, GF_LOG_ERROR, "out of memory"); - return NULL; - } - local->fop = fop; - LOCK_INIT(&local->hole_lock); - LOCK_INIT(&local->call_lock); - LOCK_INIT(&local->rw_count_lock); - - frame->local = local; - return local; -} - -struct crypt_inode_info *get_crypt_inode_info(inode_t *inode, xlator_t *this) -{ - int ret; - uint64_t value = 0; - struct crypt_inode_info *info; - - ret = inode_ctx_get(inode, this, &value); - if (ret == -1) { - gf_log (this->name, GF_LOG_WARNING, - "Can not get inode info"); - return NULL; - } - info = (struct crypt_inode_info *)(long)value; - if (info == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "Can not obtain inode info"); - return NULL; - } - return info; -} - -static struct crypt_inode_info *local_get_inode_info(crypt_local_t *local, - xlator_t *this) -{ - if (local->info) - return local->info; - local->info = get_crypt_inode_info(local->fd->inode, this); - return local->info; -} - -static struct crypt_inode_info *alloc_inode_info(crypt_local_t *local, - loc_t *loc) -{ - struct crypt_inode_info *info; - - info = GF_CALLOC(1, sizeof(struct crypt_inode_info), gf_crypt_mt_inode); - if (!info) { - local->op_ret = -1; - local->op_errno = ENOMEM; - gf_log ("crypt", GF_LOG_WARNING, - "Can not allocate inode info"); - return NULL; - } +static void +init_inode_info_head(struct crypt_inode_info *info, fd_t *fd); +static int32_t +init_inode_info_tail(struct crypt_inode_info *info, + struct master_cipher_info *master); +static int32_t +prepare_for_submit_hole(call_frame_t *frame, xlator_t *this, uint64_t from, + off_t size); +static int32_t +load_file_size(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata); +static void +do_ordered_submit(call_frame_t *frame, xlator_t *this, atom_data_type dtype); +static void +do_parallel_submit(call_frame_t *frame, xlator_t *this, atom_data_type dtype); +static void +put_one_call_open(call_frame_t *frame); +static void +put_one_call_readv(call_frame_t *frame, xlator_t *this); +static void +put_one_call_writev(call_frame_t *frame, xlator_t *this); +static void +put_one_call_ftruncate(call_frame_t *frame, xlator_t *this); +static void +free_avec(struct iovec *avec, char **pool, int blocks_in_pool); +static void +free_avec_data(crypt_local_t *local); +static void +free_avec_hole(crypt_local_t *local); + +static crypt_local_t * +crypt_alloc_local(call_frame_t *frame, xlator_t *this, glusterfs_fop_t fop) +{ + crypt_local_t *local = NULL; + + local = GF_CALLOC(1, sizeof(crypt_local_t), gf_crypt_mt_local); + if (!local) { + gf_log(this->name, GF_LOG_ERROR, "out of memory"); + return NULL; + } + local->fop = fop; + LOCK_INIT(&local->hole_lock); + LOCK_INIT(&local->call_lock); + LOCK_INIT(&local->rw_count_lock); + + frame->local = local; + return local; +} + +struct crypt_inode_info * +get_crypt_inode_info(inode_t *inode, xlator_t *this) +{ + int ret; + uint64_t value = 0; + struct crypt_inode_info *info; + + ret = inode_ctx_get(inode, this, &value); + if (ret == -1) { + gf_log(this->name, GF_LOG_WARNING, "Can not get inode info"); + return NULL; + } + info = (struct crypt_inode_info *)(long)value; + if (info == NULL) { + gf_log(this->name, GF_LOG_WARNING, "Can not obtain inode info"); + return NULL; + } + return info; +} + +static struct crypt_inode_info * +local_get_inode_info(crypt_local_t *local, xlator_t *this) +{ + if (local->info) + return local->info; + local->info = get_crypt_inode_info(local->fd->inode, this); + return local->info; +} + +static struct crypt_inode_info * +alloc_inode_info(crypt_local_t *local, loc_t *loc) +{ + struct crypt_inode_info *info; + + info = GF_CALLOC(1, sizeof(struct crypt_inode_info), gf_crypt_mt_inode); + if (!info) { + local->op_ret = -1; + local->op_errno = ENOMEM; + gf_log("crypt", GF_LOG_WARNING, "Can not allocate inode info"); + return NULL; + } #if DEBUG_CRYPT - info->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!info->loc) { - gf_log("crypt", GF_LOG_WARNING, "Can not allocate loc"); - GF_FREE(info); - return NULL; - } - if (loc_copy(info->loc, loc)){ - GF_FREE(info->loc); - GF_FREE(info); - return NULL; - } + info->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!info->loc) { + gf_log("crypt", GF_LOG_WARNING, "Can not allocate loc"); + GF_FREE(info); + return NULL; + } + if (loc_copy(info->loc, loc)) { + GF_FREE(info->loc); + GF_FREE(info); + return NULL; + } #endif /* DEBUG_CRYPT */ - local->info = info; - return info; + local->info = info; + return info; } -static void free_inode_info(struct crypt_inode_info *info) +static void +free_inode_info(struct crypt_inode_info *info) { #if DEBUG_CRYPT - loc_wipe(info->loc); - GF_FREE(info->loc); + loc_wipe(info->loc); + GF_FREE(info->loc); #endif - memset(info, 0, sizeof(*info)); - GF_FREE(info); + memset(info, 0, sizeof(*info)); + GF_FREE(info); } -int crypt_forget (xlator_t *this, inode_t *inode) +int +crypt_forget(xlator_t *this, inode_t *inode) { - uint64_t ctx_addr = 0; - if (!inode_ctx_del (inode, this, &ctx_addr)) - free_inode_info((struct crypt_inode_info *)(long)ctx_addr); - return 0; + uint64_t ctx_addr = 0; + if (!inode_ctx_del(inode, this, &ctx_addr)) + free_inode_info((struct crypt_inode_info *)(long)ctx_addr); + return 0; } #if DEBUG_CRYPT -static void check_read(call_frame_t *frame, xlator_t *this, int32_t read, - struct iovec *vec, int32_t count, struct iatt *stbuf) +static void +check_read(call_frame_t *frame, xlator_t *this, int32_t read, struct iovec *vec, + int32_t count, struct iatt *stbuf) { - crypt_local_t *local = frame->local; - struct object_cipher_info *object = get_object_cinfo(local->info); - struct avec_config *conf = &local->data_conf; - uint32_t resid = stbuf->ia_size & (object_alg_blksize(object) - 1); - - if (read <= 0) - return; - if (read != iov_length(vec, count)) - gf_log ("crypt", GF_LOG_DEBUG, - "op_ret differs from amount of read bytes"); + crypt_local_t *local = frame->local; + struct object_cipher_info *object = get_object_cinfo(local->info); + struct avec_config *conf = &local->data_conf; + uint32_t resid = stbuf->ia_size & (object_alg_blksize(object) - 1); - if (object_alg_should_pad(object) && (read & (object_alg_blksize(object) - 1))) - gf_log ("crypt", GF_LOG_DEBUG, - "bad amount of read bytes (!= 0 mod(cblock size))"); + if (read <= 0) + return; + if (read != iov_length(vec, count)) + gf_log("crypt", GF_LOG_DEBUG, + "op_ret differs from amount of read bytes"); - if (conf->aligned_offset + read > - stbuf->ia_size + (resid ? object_alg_blksize(object) - resid : 0)) - gf_log ("crypt", GF_LOG_DEBUG, - "bad amount of read bytes (too large))"); + if (object_alg_should_pad(object) && + (read & (object_alg_blksize(object) - 1))) + gf_log("crypt", GF_LOG_DEBUG, + "bad amount of read bytes (!= 0 mod(cblock size))"); + if (conf->aligned_offset + read > + stbuf->ia_size + (resid ? object_alg_blksize(object) - resid : 0)) + gf_log("crypt", GF_LOG_DEBUG, "bad amount of read bytes (too large))"); } #define PT_BYTES_TO_DUMP (32) -static void dump_plain_text(crypt_local_t *local, struct iovec *avec) -{ - int32_t to_dump; - char str[PT_BYTES_TO_DUMP + 1]; - - if (!avec) - return; - to_dump = avec->iov_len; - if (to_dump > PT_BYTES_TO_DUMP) - to_dump = PT_BYTES_TO_DUMP; - memcpy(str, avec->iov_base, to_dump); - memset(str + to_dump, '0', 1); - gf_log("crypt", GF_LOG_DEBUG, "Read file: %s", str); -} - -static int32_t data_conf_invariant(struct avec_config *conf) -{ - return conf->acount == - !!has_head_block(conf) + - !!has_tail_block(conf)+ - conf->nr_full_blocks; -} - -static int32_t hole_conf_invariant(struct avec_config *conf) -{ - return conf->blocks_in_pool == - !!has_head_block(conf) + - !!has_tail_block(conf)+ - !!has_full_blocks(conf); -} - -static void crypt_check_conf(struct avec_config *conf) -{ - int32_t ret = 0; - const char *msg; - - switch (conf->type) { - case DATA_ATOM: - msg = "data"; - ret = data_conf_invariant(conf); - break; - case HOLE_ATOM: - msg = "hole"; - ret = hole_conf_invariant(conf); - break; - default: - msg = "unknown"; - } - if (!ret) - gf_log("crypt", GF_LOG_DEBUG, "bad %s conf", msg); -} - -static void check_buf(call_frame_t *frame, xlator_t *this, struct iatt *buf) -{ - crypt_local_t *local = frame->local; - struct object_cipher_info *object = &local->info->cinfo; - uint64_t local_file_size; - - switch(local->fop) { - case GF_FOP_FTRUNCATE: - return; - case GF_FOP_WRITE: - local_file_size = local->new_file_size; - break; - case GF_FOP_READ: - if (parent_is_crypt_xlator(frame, this)) - return; - local_file_size = local->cur_file_size; - break; - default: - gf_log("crypt", GF_LOG_DEBUG, "bad file operation"); - return; - } - if (buf->ia_size != round_up(local_file_size, - object_alg_blksize(object))) - gf_log("crypt", GF_LOG_DEBUG, - "bad ia_size in buf (%llu), should be %llu", - (unsigned long long)buf->ia_size, - (unsigned long long)round_up(local_file_size, - object_alg_blksize(object))); +static void +dump_plain_text(crypt_local_t *local, struct iovec *avec) +{ + int32_t to_dump; + char str[PT_BYTES_TO_DUMP + 1]; + + if (!avec) + return; + to_dump = avec->iov_len; + if (to_dump > PT_BYTES_TO_DUMP) + to_dump = PT_BYTES_TO_DUMP; + memcpy(str, avec->iov_base, to_dump); + memset(str + to_dump, '0', 1); + gf_log("crypt", GF_LOG_DEBUG, "Read file: %s", str); +} + +static int32_t +data_conf_invariant(struct avec_config *conf) +{ + return conf->acount == !!has_head_block(conf) + !!has_tail_block(conf) + + conf->nr_full_blocks; +} + +static int32_t +hole_conf_invariant(struct avec_config *conf) +{ + return conf->blocks_in_pool == !!has_head_block(conf) + + !!has_tail_block(conf) + + !!has_full_blocks(conf); +} + +static void +crypt_check_conf(struct avec_config *conf) +{ + int32_t ret = 0; + const char *msg; + + switch (conf->type) { + case DATA_ATOM: + msg = "data"; + ret = data_conf_invariant(conf); + break; + case HOLE_ATOM: + msg = "hole"; + ret = hole_conf_invariant(conf); + break; + default: + msg = "unknown"; + } + if (!ret) + gf_log("crypt", GF_LOG_DEBUG, "bad %s conf", msg); +} + +static void +check_buf(call_frame_t *frame, xlator_t *this, struct iatt *buf) +{ + crypt_local_t *local = frame->local; + struct object_cipher_info *object = &local->info->cinfo; + uint64_t local_file_size; + + switch (local->fop) { + case GF_FOP_FTRUNCATE: + return; + case GF_FOP_WRITE: + local_file_size = local->new_file_size; + break; + case GF_FOP_READ: + if (parent_is_crypt_xlator(frame, this)) + return; + local_file_size = local->cur_file_size; + break; + default: + gf_log("crypt", GF_LOG_DEBUG, "bad file operation"); + return; + } + if (buf->ia_size != round_up(local_file_size, object_alg_blksize(object))) + gf_log("crypt", GF_LOG_DEBUG, + "bad ia_size in buf (%llu), should be %llu", + (unsigned long long)buf->ia_size, + (unsigned long long)round_up(local_file_size, + object_alg_blksize(object))); } #else @@ -262,582 +273,509 @@ static void check_buf(call_frame_t *frame, xlator_t *this, struct iatt *buf) * of data corresponding to the original size and offset. * Pass the result to the next translator. */ -int32_t crypt_readv_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vec, - int32_t count, - struct iatt *stbuf, - struct iobref *iobref, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; - struct object_cipher_info *object = &local->info->cinfo; - - struct iovec *avec; - uint32_t i; - uint32_t to_vec; - uint32_t to_user; - - check_buf(frame, this, stbuf); - check_read(frame, this, op_ret, vec, count, stbuf); - - local->op_ret = op_ret; - local->op_errno = op_errno; - local->iobref = iobref_ref(iobref); - - local->buf = *stbuf; - local->buf.ia_size = local->cur_file_size; - - if (op_ret <= 0 || count == 0 || vec[0].iov_len == 0) - goto put_one_call; - - if (conf->orig_offset >= local->cur_file_size) { - local->op_ret = 0; - goto put_one_call; - } - /* - * correct config params with real file size - * and actual amount of bytes read - */ - set_config_offsets(frame, this, - conf->orig_offset, op_ret, DATA_ATOM, 0); - - if (conf->orig_offset + conf->orig_size > local->cur_file_size) - conf->orig_size = local->cur_file_size - conf->orig_offset; - /* - * calculate amount of data to be returned - * to user. - */ - to_user = op_ret; - if (conf->aligned_offset + to_user <= conf->orig_offset) { - gf_log(this->name, GF_LOG_WARNING, "Incomplete read"); - local->op_ret = -1; - local->op_errno = EIO; - goto put_one_call; - } - to_user -= (conf->aligned_offset - conf->orig_offset); - - if (to_user > conf->orig_size) - to_user = conf->orig_size; - local->rw_count = to_user; - - op_errno = set_config_avec_data(this, local, - conf, object, vec, count); - if (op_errno) { - local->op_ret = -1; - local->op_errno = op_errno; - goto put_one_call; - } - avec = conf->avec; +int32_t +crypt_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iovec *vec, + int32_t count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata) +{ + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; + struct object_cipher_info *object = &local->info->cinfo; + + struct iovec *avec; + uint32_t i; + uint32_t to_vec; + uint32_t to_user; + + check_buf(frame, this, stbuf); + check_read(frame, this, op_ret, vec, count, stbuf); + + local->op_ret = op_ret; + local->op_errno = op_errno; + local->iobref = iobref_ref(iobref); + + local->buf = *stbuf; + local->buf.ia_size = local->cur_file_size; + + if (op_ret <= 0 || count == 0 || vec[0].iov_len == 0) + goto put_one_call; + + if (conf->orig_offset >= local->cur_file_size) { + local->op_ret = 0; + goto put_one_call; + } + /* + * correct config params with real file size + * and actual amount of bytes read + */ + set_config_offsets(frame, this, conf->orig_offset, op_ret, DATA_ATOM, 0); + + if (conf->orig_offset + conf->orig_size > local->cur_file_size) + conf->orig_size = local->cur_file_size - conf->orig_offset; + /* + * calculate amount of data to be returned + * to user. + */ + to_user = op_ret; + if (conf->aligned_offset + to_user <= conf->orig_offset) { + gf_log(this->name, GF_LOG_WARNING, "Incomplete read"); + local->op_ret = -1; + local->op_errno = EIO; + goto put_one_call; + } + to_user -= (conf->aligned_offset - conf->orig_offset); + + if (to_user > conf->orig_size) + to_user = conf->orig_size; + local->rw_count = to_user; + + op_errno = set_config_avec_data(this, local, conf, object, vec, count); + if (op_errno) { + local->op_ret = -1; + local->op_errno = op_errno; + goto put_one_call; + } + avec = conf->avec; #if DEBUG_CRYPT - if (conf->off_in_tail != 0 && - conf->off_in_tail < object_alg_blksize(object) && - object_alg_should_pad(object)) - gf_log(this->name, GF_LOG_DEBUG, "Bad offset in tail %d", - conf->off_in_tail); - if (iov_length(vec, count) != 0 && - in_same_lblock(conf->orig_offset + iov_length(vec, count) - 1, - local->cur_file_size - 1, - object_alg_blkbits(object))) { - gf_log(this->name, GF_LOG_DEBUG, "Compound last cblock"); - dump_cblock(this, - (unsigned char *)(avec[conf->acount - 1].iov_base) + - avec[conf->acount - 1].iov_len - object_alg_blksize(object)); - dump_cblock(this, - (unsigned char *)(vec[count - 1].iov_base) + - vec[count - 1].iov_len - object_alg_blksize(object)); - } + if (conf->off_in_tail != 0 && + conf->off_in_tail < object_alg_blksize(object) && + object_alg_should_pad(object)) + gf_log(this->name, GF_LOG_DEBUG, "Bad offset in tail %d", + conf->off_in_tail); + if (iov_length(vec, count) != 0 && + in_same_lblock(conf->orig_offset + iov_length(vec, count) - 1, + local->cur_file_size - 1, object_alg_blkbits(object))) { + gf_log(this->name, GF_LOG_DEBUG, "Compound last cblock"); + dump_cblock(this, (unsigned char *)(avec[conf->acount - 1].iov_base) + + avec[conf->acount - 1].iov_len - + object_alg_blksize(object)); + dump_cblock(this, (unsigned char *)(vec[count - 1].iov_base) + + vec[count - 1].iov_len - + object_alg_blksize(object)); + } #endif - decrypt_aligned_iov(object, avec, - conf->acount, conf->aligned_offset); - /* - * pass proper plain data to user - */ - avec[0].iov_base += (conf->aligned_offset - conf->orig_offset); - avec[0].iov_len -= (conf->aligned_offset - conf->orig_offset); - - to_vec = to_user; - for (i = 0; i < conf->acount; i++) { - if (avec[i].iov_len > to_vec) - avec[i].iov_len = to_vec; - to_vec -= avec[i].iov_len; - } - put_one_call: - put_one_call_readv(frame, this); - return 0; -} - -static int32_t do_readv(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict, - dict_t *xdata) -{ - data_t *data; - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto error; - /* - * extract regular file size - */ - data = dict_get(dict, FSIZE_XATTR_PREFIX); - if (!data) { - gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); - op_errno = EIO; - goto error; - } - local->cur_file_size = data_to_uint64(data); - - get_one_call(frame); - STACK_WIND(frame, - crypt_readv_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->readv, - local->fd, - /* - * FIXME: read amount can be reduced - */ - local->data_conf.expanded_size, - local->data_conf.aligned_offset, - local->flags, - local->xdata); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - - get_one_call(frame); - put_one_call_readv(frame, this); - return 0; -} - -static int32_t crypt_readv_finodelk_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto error; - /* - * An access has been granted, - * retrieve file size - */ - STACK_WIND(frame, - do_readv, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - local->fd, - FSIZE_XATTR_PREFIX, - NULL); - return 0; - error: - fd_unref(local->fd); - if (local->xdata) - dict_unref(local->xdata); - CRYPT_STACK_UNWIND(readv, - frame, - -1, - op_errno, - NULL, - 0, - NULL, - NULL, - NULL); - return 0; -} - -static int32_t readv_trivial_completion(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0) { - gf_log(this->name, GF_LOG_WARNING, - "stat failed (%d)", op_errno); - goto error; - } - local->buf = *buf; - STACK_WIND(frame, - load_file_size, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, - local->loc, - FSIZE_XATTR_PREFIX, - NULL); - return 0; - error: - CRYPT_STACK_UNWIND(readv, frame, op_ret, op_errno, - NULL, 0, NULL, NULL, NULL); - return 0; -} - -int32_t crypt_readv(call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset, - uint32_t flags, dict_t *xdata) -{ - int32_t ret; - crypt_local_t *local; - struct crypt_inode_info *info; - struct gf_flock lock = {0, }; + decrypt_aligned_iov(object, avec, conf->acount, conf->aligned_offset); + /* + * pass proper plain data to user + */ + avec[0].iov_base += (conf->aligned_offset - conf->orig_offset); + avec[0].iov_len -= (conf->aligned_offset - conf->orig_offset); + + to_vec = to_user; + for (i = 0; i < conf->acount; i++) { + if (avec[i].iov_len > to_vec) + avec[i].iov_len = to_vec; + to_vec -= avec[i].iov_len; + } +put_one_call: + put_one_call_readv(frame, this); + return 0; +} + +static int32_t +do_readv(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + data_t *data; + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto error; + /* + * extract regular file size + */ + data = dict_get(dict, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + op_errno = EIO; + goto error; + } + local->cur_file_size = data_to_uint64(data); + + get_one_call(frame); + STACK_WIND(frame, crypt_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, local->fd, + /* + * FIXME: read amount can be reduced + */ + local->data_conf.expanded_size, local->data_conf.aligned_offset, + local->flags, local->xdata); + return 0; +error: + local->op_ret = -1; + local->op_errno = op_errno; + + get_one_call(frame); + put_one_call_readv(frame, this); + return 0; +} + +static int32_t +crypt_readv_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto error; + /* + * An access has been granted, + * retrieve file size + */ + STACK_WIND(frame, do_readv, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, local->fd, + FSIZE_XATTR_PREFIX, NULL); + return 0; +error: + fd_unref(local->fd); + if (local->xdata) + dict_unref(local->xdata); + CRYPT_STACK_UNWIND(readv, frame, -1, op_errno, NULL, 0, NULL, NULL, NULL); + return 0; +} + +static int32_t +readv_trivial_completion(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) { + gf_log(this->name, GF_LOG_WARNING, "stat failed (%d)", op_errno); + goto error; + } + local->buf = *buf; + STACK_WIND(frame, load_file_size, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, local->loc, + FSIZE_XATTR_PREFIX, NULL); + return 0; +error: + CRYPT_STACK_UNWIND(readv, frame, op_ret, op_errno, NULL, 0, NULL, NULL, + NULL); + return 0; +} + +int32_t +crypt_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) +{ + int32_t ret; + crypt_local_t *local; + struct crypt_inode_info *info; + struct gf_flock lock = { + 0, + }; #if DEBUG_CRYPT - gf_log("crypt", GF_LOG_DEBUG, "reading %d bytes from offset %llu", - (int)size, (long long)offset); - if (parent_is_crypt_xlator(frame, this)) - gf_log("crypt", GF_LOG_DEBUG, "parent is crypt"); + gf_log("crypt", GF_LOG_DEBUG, "reading %d bytes from offset %llu", + (int)size, (long long)offset); + if (parent_is_crypt_xlator(frame, this)) + gf_log("crypt", GF_LOG_DEBUG, "parent is crypt"); #endif - local = crypt_alloc_local(frame, this, GF_FOP_READ); - if (!local) { - ret = ENOMEM; - goto error; - } - if (size == 0) - goto trivial; - - local->fd = fd_ref(fd); - local->flags = flags; - - info = local_get_inode_info(local, this); - if (info == NULL) { - ret = EINVAL; - fd_unref(fd); - goto error; - } - if (!object_alg_atomic(&info->cinfo)) { - ret = EINVAL; - fd_unref(fd); - goto error; - } - set_config_offsets(frame, this, offset, size, - DATA_ATOM, 0); - if (parent_is_crypt_xlator(frame, this)) { - data_t *data; - /* - * We are called by crypt_writev (or cypt_ftruncate) - * to perform the "read" component of the read-modify-write - * (or read-prune-write) sequence for some atom; - * - * don't ask for access: - * it has already been acquired - * - * Retrieve current file size - */ - if (!xdata) { - gf_log("crypt", GF_LOG_WARNING, - "Regular file size hasn't been passed"); - ret = EIO; - goto error; - } - data = dict_get(xdata, FSIZE_XATTR_PREFIX); - if (!data) { - gf_log("crypt", GF_LOG_WARNING, - "Regular file size not found"); - ret = EIO; - goto error; - } - local->old_file_size = - local->cur_file_size = data_to_uint64(data); - - get_one_call(frame); - STACK_WIND(frame, - crypt_readv_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, - local->fd, - /* - * FIXME: read amount can be reduced - */ - local->data_conf.expanded_size, - local->data_conf.aligned_offset, - flags, - NULL); - return 0; - } - if (xdata) - local->xdata = dict_ref(xdata); - - lock.l_len = 0; - lock.l_start = 0; - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; + local = crypt_alloc_local(frame, this, GF_FOP_READ); + if (!local) { + ret = ENOMEM; + goto error; + } + if (size == 0) + goto trivial; + + local->fd = fd_ref(fd); + local->flags = flags; + + info = local_get_inode_info(local, this); + if (info == NULL) { + ret = EINVAL; + fd_unref(fd); + goto error; + } + if (!object_alg_atomic(&info->cinfo)) { + ret = EINVAL; + fd_unref(fd); + goto error; + } + set_config_offsets(frame, this, offset, size, DATA_ATOM, 0); + if (parent_is_crypt_xlator(frame, this)) { + data_t *data; + /* + * We are called by crypt_writev (or cypt_ftruncate) + * to perform the "read" component of the read-modify-write + * (or read-prune-write) sequence for some atom; + * + * don't ask for access: + * it has already been acquired + * + * Retrieve current file size + */ + if (!xdata) { + gf_log("crypt", GF_LOG_WARNING, + "Regular file size hasn't been passed"); + ret = EIO; + goto error; + } + data = dict_get(xdata, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + ret = EIO; + goto error; + } + local->old_file_size = local->cur_file_size = data_to_uint64(data); + + get_one_call(frame); + STACK_WIND(frame, crypt_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, local->fd, + /* + * FIXME: read amount can be reduced + */ + local->data_conf.expanded_size, + local->data_conf.aligned_offset, flags, NULL); + return 0; + } + if (xdata) + local->xdata = dict_ref(xdata); + + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND(frame, crypt_readv_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, fd, F_SETLKW, + &lock, NULL); + return 0; +trivial: + STACK_WIND(frame, readv_trivial_completion, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, NULL); + return 0; +error: + CRYPT_STACK_UNWIND(readv, frame, -1, ret, NULL, 0, NULL, NULL, NULL); + return 0; +} + +void +set_local_io_params_writev(call_frame_t *frame, + struct object_cipher_info *object, + struct rmw_atom *atom, off_t io_offset, + uint32_t io_size) +{ + crypt_local_t *local = frame->local; + + local->io_offset = io_offset; + local->io_size = io_size; + + local->io_offset_nopad = atom->offset_at(frame, object) + + atom->offset_in(frame, object); + + gf_log("crypt", GF_LOG_DEBUG, "set nopad offset to %llu", + (unsigned long long)local->io_offset_nopad); + + local->io_size_nopad = atom->io_size_nopad(frame, object); + + gf_log("crypt", GF_LOG_DEBUG, "set nopad size to %llu", + (unsigned long long)local->io_size_nopad); + + local->update_disk_file_size = 0; + /* + * NOTE: eof_padding_size is 0 for all full atoms; + * For head and tail atoms it will be set up at rmw_partial block() + */ + local->new_file_size = local->cur_file_size; + + if (local->io_offset_nopad + local->io_size_nopad > local->cur_file_size) { + local->new_file_size = local->io_offset_nopad + local->io_size_nopad; + + gf_log("crypt", GF_LOG_DEBUG, "set new file size to %llu", + (unsigned long long)local->new_file_size); + + local->update_disk_file_size = 1; + } +} + +void +set_local_io_params_ftruncate(call_frame_t *frame, + struct object_cipher_info *object) +{ + uint32_t resid; + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; + + resid = conf->orig_offset & (object_alg_blksize(object) - 1); + if (resid) { + local->eof_padding_size = object_alg_blksize(object) - resid; + local->new_file_size = conf->aligned_offset; + local->update_disk_file_size = 0; + /* + * file size will be updated + * in the ->writev() stack, + * when submitting file tail + */ + } else { + local->eof_padding_size = 0; + local->new_file_size = conf->orig_offset; + local->update_disk_file_size = 1; + /* + * file size will be updated + * in this ->ftruncate stack + */ + } +} + +static void +submit_head(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + submit_partial(frame, this, local->fd, HEAD_ATOM); +} - STACK_WIND(frame, - crypt_readv_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - fd, - F_SETLKW, - &lock, - NULL); - return 0; - trivial: - STACK_WIND(frame, - readv_trivial_completion, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, - fd, - NULL); - return 0; - error: - CRYPT_STACK_UNWIND(readv, - frame, - -1, - ret, - NULL, - 0, - NULL, - NULL, - NULL); - return 0; -} - -void set_local_io_params_writev(call_frame_t *frame, - struct object_cipher_info *object, - struct rmw_atom *atom, - off_t io_offset, - uint32_t io_size) -{ - crypt_local_t *local = frame->local; - - local->io_offset = io_offset; - local->io_size = io_size; - - local->io_offset_nopad = - atom->offset_at(frame, object) + atom->offset_in(frame, object); - - gf_log("crypt", GF_LOG_DEBUG, - "set nopad offset to %llu", - (unsigned long long)local->io_offset_nopad); - - local->io_size_nopad = atom->io_size_nopad(frame, object); - - gf_log("crypt", GF_LOG_DEBUG, - "set nopad size to %llu", - (unsigned long long)local->io_size_nopad); - - local->update_disk_file_size = 0; - /* - * NOTE: eof_padding_size is 0 for all full atoms; - * For head and tail atoms it will be set up at rmw_partial block() - */ - local->new_file_size = local->cur_file_size; - - if (local->io_offset_nopad + local->io_size_nopad > local->cur_file_size) { - - local->new_file_size = local->io_offset_nopad + local->io_size_nopad; - - gf_log("crypt", GF_LOG_DEBUG, - "set new file size to %llu", - (unsigned long long)local->new_file_size); - - local->update_disk_file_size = 1; - } -} - -void set_local_io_params_ftruncate(call_frame_t *frame, - struct object_cipher_info *object) -{ - uint32_t resid; - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; - - resid = conf->orig_offset & (object_alg_blksize(object) - 1); - if (resid) { - local->eof_padding_size = - object_alg_blksize(object) - resid; - local->new_file_size = conf->aligned_offset; - local->update_disk_file_size = 0; - /* - * file size will be updated - * in the ->writev() stack, - * when submitting file tail - */ - } else { - local->eof_padding_size = 0; - local->new_file_size = conf->orig_offset; - local->update_disk_file_size = 1; - /* - * file size will be updated - * in this ->ftruncate stack - */ - } -} - -static void submit_head(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - submit_partial(frame, this, local->fd, HEAD_ATOM); -} - -static void submit_tail(call_frame_t *frame, xlator_t *this) +static void +submit_tail(call_frame_t *frame, xlator_t *this) { - crypt_local_t *local = frame->local; - submit_partial(frame, this, local->fd, TAIL_ATOM); + crypt_local_t *local = frame->local; + submit_partial(frame, this, local->fd, TAIL_ATOM); } -static void submit_hole(call_frame_t *frame, xlator_t *this) +static void +submit_hole(call_frame_t *frame, xlator_t *this) { - /* - * hole conversion always means - * appended write and goes in ordered fashion - */ - do_ordered_submit(frame, this, HOLE_ATOM); + /* + * hole conversion always means + * appended write and goes in ordered fashion + */ + do_ordered_submit(frame, this, HOLE_ATOM); } -static void submit_data(call_frame_t *frame, xlator_t *this) +static void +submit_data(call_frame_t *frame, xlator_t *this) { - if (is_ordered_mode(frame)) { - do_ordered_submit(frame, this, DATA_ATOM); - return; - } - gf_log("crypt", GF_LOG_WARNING, "Bad submit mode"); - get_nr_calls(frame, nr_calls_data(frame)); - do_parallel_submit(frame, this, DATA_ATOM); - return; + if (is_ordered_mode(frame)) { + do_ordered_submit(frame, this, DATA_ATOM); + return; + } + gf_log("crypt", GF_LOG_WARNING, "Bad submit mode"); + get_nr_calls(frame, nr_calls_data(frame)); + do_parallel_submit(frame, this, DATA_ATOM); + return; } /* * heplers called by writev_cbk, fruncate_cbk in ordered mode */ -static int32_t should_submit_hole(crypt_local_t *local) +static int32_t +should_submit_hole(crypt_local_t *local) { - struct avec_config *conf = &local->hole_conf; + struct avec_config *conf = &local->hole_conf; - return conf->avec != NULL; + return conf->avec != NULL; } -static int32_t should_resume_submit_hole(crypt_local_t *local) +static int32_t +should_resume_submit_hole(crypt_local_t *local) { - struct avec_config *conf = &local->hole_conf; + struct avec_config *conf = &local->hole_conf; - if (local->fop == GF_FOP_WRITE && has_tail_block(conf)) - /* - * Don't submit a part of hole, which - * fits into a data block: - * this part of hole will be converted - * as a gap filled by zeros in data head - * block. - */ - return conf->cursor < conf->acount - 1; - else - return conf->cursor < conf->acount; + if (local->fop == GF_FOP_WRITE && has_tail_block(conf)) + /* + * Don't submit a part of hole, which + * fits into a data block: + * this part of hole will be converted + * as a gap filled by zeros in data head + * block. + */ + return conf->cursor < conf->acount - 1; + else + return conf->cursor < conf->acount; } -static int32_t should_resume_submit_data(call_frame_t *frame) +static int32_t +should_resume_submit_data(call_frame_t *frame) { - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; - if (is_ordered_mode(frame)) - return conf->cursor < conf->acount; - /* - * parallel writes - */ - return 0; + if (is_ordered_mode(frame)) + return conf->cursor < conf->acount; + /* + * parallel writes + */ + return 0; } -static int32_t should_submit_data_after_hole(crypt_local_t *local) +static int32_t +should_submit_data_after_hole(crypt_local_t *local) { - return local->data_conf.avec != NULL; + return local->data_conf.avec != NULL; } -static void update_local_file_params(call_frame_t *frame, - xlator_t *this, - struct iatt *prebuf, - struct iatt *postbuf) +static void +update_local_file_params(call_frame_t *frame, xlator_t *this, + struct iatt *prebuf, struct iatt *postbuf) { - crypt_local_t *local = frame->local; + crypt_local_t *local = frame->local; - check_buf(frame, this, postbuf); + check_buf(frame, this, postbuf); - local->prebuf = *prebuf; - local->postbuf = *postbuf; + local->prebuf = *prebuf; + local->postbuf = *postbuf; - local->prebuf.ia_size = local->cur_file_size; - local->postbuf.ia_size = local->new_file_size; + local->prebuf.ia_size = local->cur_file_size; + local->postbuf.ia_size = local->new_file_size; - local->cur_file_size = local->new_file_size; + local->cur_file_size = local->new_file_size; } -static int32_t end_writeback_writev(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf, - dict_t *xdata) +static int32_t +end_writeback_writev(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) { - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; + crypt_local_t *local = frame->local; - if (op_ret <= 0) { - gf_log(this->name, GF_LOG_WARNING, - "writev iteration failed"); - goto put_one_call; - } - /* - * op_ret includes paddings (atom's head, atom's tail and EOF) - */ - if (op_ret < local->io_size) { - gf_log(this->name, GF_LOG_WARNING, - "Incomplete writev iteration"); - goto put_one_call; - } - op_ret -= local->eof_padding_size; - local->op_ret = op_ret; + local->op_ret = op_ret; + local->op_errno = op_errno; - update_local_file_params(frame, this, prebuf, postbuf); + if (op_ret <= 0) { + gf_log(this->name, GF_LOG_WARNING, "writev iteration failed"); + goto put_one_call; + } + /* + * op_ret includes paddings (atom's head, atom's tail and EOF) + */ + if (op_ret < local->io_size) { + gf_log(this->name, GF_LOG_WARNING, "Incomplete writev iteration"); + goto put_one_call; + } + op_ret -= local->eof_padding_size; + local->op_ret = op_ret; - if (data_write_in_progress(local)) { + update_local_file_params(frame, this, prebuf, postbuf); - LOCK(&local->rw_count_lock); - local->rw_count += op_ret; - UNLOCK(&local->rw_count_lock); + if (data_write_in_progress(local)) { + LOCK(&local->rw_count_lock); + local->rw_count += op_ret; + UNLOCK(&local->rw_count_lock); - if (should_resume_submit_data(frame)) - submit_data(frame, this); - } - else { - /* - * hole conversion is going on; - * don't take into account written zeros - */ - if (should_resume_submit_hole(local)) - submit_hole(frame, this); + if (should_resume_submit_data(frame)) + submit_data(frame, this); + } else { + /* + * hole conversion is going on; + * don't take into account written zeros + */ + if (should_resume_submit_hole(local)) + submit_hole(frame, this); - else if (should_submit_data_after_hole(local)) - submit_data(frame, this); - } - put_one_call: - put_one_call_writev(frame, this); - return 0; + else if (should_submit_data_after_hole(local)) + submit_data(frame, this); + } +put_one_call: + put_one_call_writev(frame, this); + return 0; } #define crypt_writev_cbk end_writeback_writev @@ -853,363 +791,331 @@ static int32_t end_writeback_writev(call_frame_t *frame, * Pre-conditions: * @local->file_size is set and valid. */ -int32_t prepare_for_submit_hole(call_frame_t *frame, xlator_t *this, - uint64_t off, off_t size) +int32_t +prepare_for_submit_hole(call_frame_t *frame, xlator_t *this, uint64_t off, + off_t size) { - int32_t ret; - crypt_local_t *local = frame->local; - struct object_cipher_info *object = &local->info->cinfo; + int32_t ret; + crypt_local_t *local = frame->local; + struct object_cipher_info *object = &local->info->cinfo; - set_config_offsets(frame, this, off, size, HOLE_ATOM, 1); + set_config_offsets(frame, this, off, size, HOLE_ATOM, 1); - ret = set_config_avec_hole(this, local, - &local->hole_conf, object, local->fop); - crypt_check_conf(&local->hole_conf); + ret = set_config_avec_hole(this, local, &local->hole_conf, object, + local->fop); + crypt_check_conf(&local->hole_conf); - return ret; + return ret; } /* * prepare for submit @count bytes at offset @from */ -int32_t prepare_for_submit_data(call_frame_t *frame, xlator_t *this, - off_t from, int32_t size, struct iovec *vec, - int32_t vec_count, int32_t setup_gap) +int32_t +prepare_for_submit_data(call_frame_t *frame, xlator_t *this, off_t from, + int32_t size, struct iovec *vec, int32_t vec_count, + int32_t setup_gap) { - uint32_t ret; - crypt_local_t *local = frame->local; - struct object_cipher_info *object = &local->info->cinfo; + uint32_t ret; + crypt_local_t *local = frame->local; + struct object_cipher_info *object = &local->info->cinfo; - set_config_offsets(frame, this, from, size, - DATA_ATOM, setup_gap); + set_config_offsets(frame, this, from, size, DATA_ATOM, setup_gap); - ret = set_config_avec_data(this, local, - &local->data_conf, object, vec, vec_count); - crypt_check_conf(&local->data_conf); + ret = set_config_avec_data(this, local, &local->data_conf, object, vec, + vec_count); + crypt_check_conf(&local->data_conf); - return ret; + return ret; +} + +static void +free_avec(struct iovec *avec, char **pool, int blocks_in_pool) +{ + if (!avec) + return; + GF_FREE(pool); + GF_FREE(avec); +} + +static void +free_avec_data(crypt_local_t *local) +{ + return free_avec(local->data_conf.avec, local->data_conf.pool, + local->data_conf.blocks_in_pool); +} + +static void +free_avec_hole(crypt_local_t *local) +{ + return free_avec(local->hole_conf.avec, local->hole_conf.pool, + local->hole_conf.blocks_in_pool); +} + +static void +do_parallel_submit(call_frame_t *frame, xlator_t *this, atom_data_type dtype) +{ + crypt_local_t *local = frame->local; + struct avec_config *conf; + + local->active_setup = dtype; + conf = conf_by_type(frame, dtype); + + if (has_head_block(conf)) + submit_head(frame, this); + + if (has_full_blocks(conf)) + submit_full(frame, this); + + if (has_tail_block(conf)) + submit_tail(frame, this); + return; +} + +static void +do_ordered_submit(call_frame_t *frame, xlator_t *this, atom_data_type dtype) +{ + crypt_local_t *local = frame->local; + struct avec_config *conf; + + local->active_setup = dtype; + conf = conf_by_type(frame, dtype); + + if (should_submit_head_block(conf)) { + get_one_call_nolock(frame); + submit_head(frame, this); + } else if (should_submit_full_block(conf)) { + get_one_call_nolock(frame); + submit_full(frame, this); + } else if (should_submit_tail_block(conf)) { + get_one_call_nolock(frame); + submit_tail(frame, this); + } else + gf_log("crypt", GF_LOG_DEBUG, + "nothing has been submitted in ordered mode"); + return; +} + +static int32_t +do_writev(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + data_t *data; + crypt_local_t *local = frame->local; + struct object_cipher_info *object = &local->info->cinfo; + /* + * extract regular file size + */ + data = dict_get(dict, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + op_ret = -1; + op_errno = EIO; + goto error; + } + local->old_file_size = local->cur_file_size = data_to_uint64(data); + + set_gap_at_end(frame, object, &local->data_conf, DATA_ATOM); + + if (local->cur_file_size < local->data_conf.orig_offset) { + /* + * Set up hole config + */ + op_errno = prepare_for_submit_hole( + frame, this, local->cur_file_size, + local->data_conf.orig_offset - local->cur_file_size); + if (op_errno) { + local->op_ret = -1; + local->op_errno = op_errno; + goto error; + } + } + if (should_submit_hole(local)) + submit_hole(frame, this); + else + submit_data(frame, this); + return 0; +error: + get_one_call_nolock(frame); + put_one_call_writev(frame, this); + return 0; +} + +static int32_t +crypt_writev_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) + goto error; + /* + * An access has been granted, + * retrieve file size first + */ + STACK_WIND(frame, do_writev, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, local->fd, + FSIZE_XATTR_PREFIX, NULL); + return 0; +error: + get_one_call_nolock(frame); + put_one_call_writev(frame, this); + return 0; } -static void free_avec(struct iovec *avec, - char **pool, int blocks_in_pool) +static int32_t +writev_trivial_completion(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *dict) { - if (!avec) - return; - GF_FREE(pool); - GF_FREE(avec); + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + local->prebuf = *buf; + local->postbuf = *buf; + + local->prebuf.ia_size = local->cur_file_size; + local->postbuf.ia_size = local->cur_file_size; + + get_one_call(frame); + put_one_call_writev(frame, this); + return 0; } -static void free_avec_data(crypt_local_t *local) -{ - return free_avec(local->data_conf.avec, - local->data_conf.pool, - local->data_conf.blocks_in_pool); -} - -static void free_avec_hole(crypt_local_t *local) -{ - return free_avec(local->hole_conf.avec, - local->hole_conf.pool, - local->hole_conf.blocks_in_pool); -} - - -static void do_parallel_submit(call_frame_t *frame, xlator_t *this, - atom_data_type dtype) -{ - crypt_local_t *local = frame->local; - struct avec_config *conf; - - local->active_setup = dtype; - conf = conf_by_type(frame, dtype); - - if (has_head_block(conf)) - submit_head(frame, this); - - if (has_full_blocks(conf)) - submit_full(frame, this); - - if (has_tail_block(conf)) - submit_tail(frame, this); - return; -} - -static void do_ordered_submit(call_frame_t *frame, xlator_t *this, - atom_data_type dtype) -{ - crypt_local_t *local = frame->local; - struct avec_config *conf; - - local->active_setup = dtype; - conf = conf_by_type(frame, dtype); - - if (should_submit_head_block(conf)) { - get_one_call_nolock(frame); - submit_head(frame, this); - } - else if (should_submit_full_block(conf)) { - get_one_call_nolock(frame); - submit_full(frame, this); - } - else if (should_submit_tail_block(conf)) { - get_one_call_nolock(frame); - submit_tail(frame, this); - } - else - gf_log("crypt", GF_LOG_DEBUG, - "nothing has been submitted in ordered mode"); - return; -} - -static int32_t do_writev(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict, - dict_t *xdata) -{ - data_t *data; - crypt_local_t *local = frame->local; - struct object_cipher_info *object = &local->info->cinfo; - /* - * extract regular file size - */ - data = dict_get(dict, FSIZE_XATTR_PREFIX); - if (!data) { - gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); - op_ret = -1; - op_errno = EIO; - goto error; - } - local->old_file_size = local->cur_file_size = data_to_uint64(data); - - set_gap_at_end(frame, object, &local->data_conf, DATA_ATOM); - - if (local->cur_file_size < local->data_conf.orig_offset) { - /* - * Set up hole config - */ - op_errno = prepare_for_submit_hole(frame, - this, - local->cur_file_size, - local->data_conf.orig_offset - local->cur_file_size); - if (op_errno) { - local->op_ret = -1; - local->op_errno = op_errno; - goto error; - } - } - if (should_submit_hole(local)) - submit_hole(frame, this); - else - submit_data(frame, this); - return 0; - error: - get_one_call_nolock(frame); - put_one_call_writev(frame, this); - return 0; -} - -static int32_t crypt_writev_finodelk_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0) - goto error; - /* - * An access has been granted, - * retrieve file size first - */ - STACK_WIND(frame, - do_writev, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - local->fd, - FSIZE_XATTR_PREFIX, - NULL); - return 0; - error: - get_one_call_nolock(frame); - put_one_call_writev(frame, this); - return 0; -} - -static int32_t writev_trivial_completion(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - dict_t *dict) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - local->prebuf = *buf; - local->postbuf = *buf; - - local->prebuf.ia_size = local->cur_file_size; - local->postbuf.ia_size = local->cur_file_size; - - get_one_call(frame); - put_one_call_writev(frame, this); - return 0; -} - -int crypt_writev(call_frame_t *frame, - xlator_t *this, - fd_t *fd, - struct iovec *vec, - int32_t count, - off_t offset, - uint32_t flags, - struct iobref *iobref, - dict_t *xdata) -{ - int32_t ret; - crypt_local_t *local; - struct crypt_inode_info *info; - struct gf_flock lock = {0, }; +int +crypt_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vec, + int32_t count, off_t offset, uint32_t flags, struct iobref *iobref, + dict_t *xdata) +{ + int32_t ret; + crypt_local_t *local; + struct crypt_inode_info *info; + struct gf_flock lock = { + 0, + }; #if DEBUG_CRYPT - gf_log ("crypt", GF_LOG_DEBUG, "writing %d bytes from offset %llu", - (int)iov_length(vec, count), (long long)offset); + gf_log("crypt", GF_LOG_DEBUG, "writing %d bytes from offset %llu", + (int)iov_length(vec, count), (long long)offset); #endif - local = crypt_alloc_local(frame, this, GF_FOP_WRITE); - if (!local) { - ret = ENOMEM; - goto error; - } - local->fd = fd_ref(fd); - - if (iobref) - local->iobref = iobref_ref(iobref); - /* - * to update real file size on the server - */ - local->xattr = dict_new(); - if (!local->xattr) { - ret = ENOMEM; - goto error; - } - local->flags = flags; - - info = local_get_inode_info(local, this); - if (info == NULL) { - ret = EINVAL; - goto error; - } - if (!object_alg_atomic(&info->cinfo)) { - ret = EINVAL; - goto error; - } - if (iov_length(vec, count) == 0) - goto trivial; - - ret = prepare_for_submit_data(frame, this, offset, + local = crypt_alloc_local(frame, this, GF_FOP_WRITE); + if (!local) { + ret = ENOMEM; + goto error; + } + local->fd = fd_ref(fd); + + if (iobref) + local->iobref = iobref_ref(iobref); + /* + * to update real file size on the server + */ + local->xattr = dict_new(); + if (!local->xattr) { + ret = ENOMEM; + goto error; + } + local->flags = flags; + + info = local_get_inode_info(local, this); + if (info == NULL) { + ret = EINVAL; + goto error; + } + if (!object_alg_atomic(&info->cinfo)) { + ret = EINVAL; + goto error; + } + if (iov_length(vec, count) == 0) + goto trivial; + + ret = prepare_for_submit_data(frame, this, offset, iov_length(vec, count), vec, count, 0 /* don't setup gup in tail: we don't know file size yet */); - if (ret) { - ret = ENOMEM; - goto error; + if (ret) { + ret = ENOMEM; + goto error; + } + + if (parent_is_crypt_xlator(frame, this)) { + data_t *data; + /* + * we are called by shinking crypt_ftruncate(), + * which doesn't perform hole conversion; + * + * don't ask for access: + * it has already been acquired + */ + + /* + * extract file size + */ + if (!xdata) { + gf_log("crypt", GF_LOG_WARNING, + "Regular file size hasn't been passed"); + ret = EIO; + goto error; } + data = dict_get(xdata, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + ret = EIO; + goto error; + } + local->old_file_size = local->cur_file_size = data_to_uint64(data); - if (parent_is_crypt_xlator(frame, this)) { - data_t *data; - /* - * we are called by shinking crypt_ftruncate(), - * which doesn't perform hole conversion; - * - * don't ask for access: - * it has already been acquired - */ - - /* - * extract file size - */ - if (!xdata) { - gf_log("crypt", GF_LOG_WARNING, - "Regular file size hasn't been passed"); - ret = EIO; - goto error; - } - data = dict_get(xdata, FSIZE_XATTR_PREFIX); - if (!data) { - gf_log("crypt", GF_LOG_WARNING, - "Regular file size not found"); - ret = EIO; - goto error; - } - local->old_file_size = - local->cur_file_size = data_to_uint64(data); - - submit_data(frame, this); - return 0; - } - if (xdata) - local->xdata = dict_ref(xdata); - /* - * lock the file and retrieve its size - */ - lock.l_len = 0; - lock.l_start = 0; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; + submit_data(frame, this); + return 0; + } + if (xdata) + local->xdata = dict_ref(xdata); + /* + * lock the file and retrieve its size + */ + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND(frame, crypt_writev_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, fd, F_SETLKW, + &lock, NULL); + return 0; +trivial: + STACK_WIND(frame, writev_trivial_completion, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, NULL); + return 0; +error: + if (local && local->fd) + fd_unref(fd); + if (local && local->iobref) + iobref_unref(iobref); + if (local && local->xdata) + dict_unref(xdata); + if (local && local->xattr) + dict_unref(local->xattr); + if (local && local->info) + free_inode_info(local->info); - STACK_WIND(frame, - crypt_writev_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - fd, - F_SETLKW, - &lock, - NULL); - return 0; - trivial: - STACK_WIND(frame, - writev_trivial_completion, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, - fd, - NULL); - return 0; - error: - if (local && local->fd) - fd_unref(fd); - if (local && local->iobref) - iobref_unref(iobref); - if (local && local->xdata) - dict_unref(xdata); - if (local && local->xattr) - dict_unref(local->xattr); - if (local && local->info) - free_inode_info(local->info); - - CRYPT_STACK_UNWIND(writev, frame, -1, ret, NULL, NULL, NULL); - return 0; -} - -int32_t prepare_for_prune(call_frame_t *frame, xlator_t *this, uint64_t offset) -{ - set_config_offsets(frame, this, + CRYPT_STACK_UNWIND(writev, frame, -1, ret, NULL, NULL, NULL); + return 0; +} + +int32_t +prepare_for_prune(call_frame_t *frame, xlator_t *this, uint64_t offset) +{ + set_config_offsets(frame, this, offset, 0, /* count */ DATA_ATOM, 0 /* since we prune, there is no gap in tail to uptodate */); - return 0; + return 0; } /* @@ -1220,24 +1126,20 @@ int32_t prepare_for_prune(call_frame_t *frame, xlator_t *this, uint64_t offset) * 2) ->writev_cbk() for non-cblock-aligned prune */ -static int32_t prune_complete(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf, - dict_t *xdata) +static int32_t +prune_complete(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) { - crypt_local_t *local = frame->local; + crypt_local_t *local = frame->local; - local->op_ret = op_ret; - local->op_errno = op_errno; + local->op_ret = op_ret; + local->op_errno = op_errno; - update_local_file_params(frame, this, prebuf, postbuf); + update_local_file_params(frame, this, prebuf, postbuf); - put_one_call_ftruncate(frame, this); - return 0; + put_one_call_ftruncate(frame, this); + return 0; } /* @@ -1248,81 +1150,69 @@ static int32_t prune_complete(call_frame_t *frame, * * submuit the rest of the file */ -static int32_t prune_submit_file_tail(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; - dict_t *dict; - - if (op_ret < 0) - goto put_one_call; - - if (local->xdata) { - dict_unref(local->xdata); - local->xdata = NULL; - } - if (xdata) - local->xdata = dict_ref(xdata); - - dict = dict_new(); - if (!dict) { - op_errno = ENOMEM; - goto error; - } - - update_local_file_params(frame, this, prebuf, postbuf); - local->new_file_size = conf->orig_offset; - - /* - * The rest of the file is a partial block and, hence, - * should be written via RMW sequence, so the crypt xlator - * does STACK_WIND to itself. - * - * Pass current file size to crypt_writev() - */ - op_errno = dict_set(dict, - FSIZE_XATTR_PREFIX, - data_from_uint64(local->cur_file_size)); - if (op_errno) { - gf_log("crypt", GF_LOG_WARNING, - "can not set key to update file size"); - dict_unref(dict); - goto error; - } - gf_log("crypt", GF_LOG_DEBUG, - "passing current file size (%llu) to crypt_writev", - (unsigned long long)local->cur_file_size); - /* - * Padding will be filled with - * zeros by rmw_partial_block() - */ - STACK_WIND(frame, - prune_complete, - this, - this->fops->writev, /* crypt_writev */ - local->fd, - &local->vec, - 1, - conf->aligned_offset, /* offset to write from */ - 0, - local->iobref, - dict); - - dict_unref(dict); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - put_one_call: - put_one_call_ftruncate(frame, this); - return 0; +static int32_t +prune_submit_file_tail(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; + dict_t *dict; + + if (op_ret < 0) + goto put_one_call; + + if (local->xdata) { + dict_unref(local->xdata); + local->xdata = NULL; + } + if (xdata) + local->xdata = dict_ref(xdata); + + dict = dict_new(); + if (!dict) { + op_errno = ENOMEM; + goto error; + } + + update_local_file_params(frame, this, prebuf, postbuf); + local->new_file_size = conf->orig_offset; + + /* + * The rest of the file is a partial block and, hence, + * should be written via RMW sequence, so the crypt xlator + * does STACK_WIND to itself. + * + * Pass current file size to crypt_writev() + */ + op_errno = dict_set(dict, FSIZE_XATTR_PREFIX, + data_from_uint64(local->cur_file_size)); + if (op_errno) { + gf_log("crypt", GF_LOG_WARNING, "can not set key to update file size"); + dict_unref(dict); + goto error; + } + gf_log("crypt", GF_LOG_DEBUG, + "passing current file size (%llu) to crypt_writev", + (unsigned long long)local->cur_file_size); + /* + * Padding will be filled with + * zeros by rmw_partial_block() + */ + STACK_WIND(frame, prune_complete, this, + this->fops->writev, /* crypt_writev */ + local->fd, &local->vec, 1, + conf->aligned_offset, /* offset to write from */ + 0, local->iobref, dict); + + dict_unref(dict); + return 0; +error: + local->op_ret = -1; + local->op_errno = op_errno; +put_one_call: + put_one_call_ftruncate(frame, this); + return 0; } /* @@ -1333,40 +1223,36 @@ static int32_t prune_submit_file_tail(call_frame_t *frame, * 2) an rmw partial data block issued by non-cblock-aligned * prune. */ -int32_t end_writeback_ftruncate(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - /* - * if nothing has been written, - * then it must be an error - */ - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0) - goto put_one_call; - - update_local_file_params(frame, this, prebuf, postbuf); - - if (data_write_in_progress(local)) - /* case (2) */ - goto put_one_call; - /* case (1) */ - if (should_resume_submit_hole(local)) - submit_hole(frame, this); - /* - * case of hole, when we shouldn't resume - */ - put_one_call: - put_one_call_ftruncate(frame, this); - return 0; +int32_t +end_writeback_ftruncate(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + /* + * if nothing has been written, + * then it must be an error + */ + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) + goto put_one_call; + + update_local_file_params(frame, this, prebuf, postbuf); + + if (data_write_in_progress(local)) + /* case (2) */ + goto put_one_call; + /* case (1) */ + if (should_resume_submit_hole(local)) + submit_hole(frame, this); + /* + * case of hole, when we shouldn't resume + */ +put_one_call: + put_one_call_ftruncate(frame, this); + return 0; } /* @@ -1379,150 +1265,126 @@ int32_t end_writeback_ftruncate(call_frame_t *frame, * @vec contains the latest atom of the file * (plain text) */ -static int32_t prune_write(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vec, - int32_t count, - struct iatt *stbuf, - struct iobref *iobref, - dict_t *xdata) -{ - int32_t i; - size_t to_copy; - size_t copied = 0; - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; - - local->op_ret = op_ret; - local->op_errno = op_errno; - if (op_ret == -1) - goto put_one_call; - - /* - * At first, uptodate head block - */ - if (iov_length(vec, count) < conf->off_in_head) { - gf_log(this->name, GF_LOG_WARNING, - "Failed to uptodate head block for prune"); - local->op_ret = -1; - local->op_errno = EIO; - goto put_one_call; - } - local->vec.iov_len = conf->off_in_head; - local->vec.iov_base = GF_CALLOC(1, local->vec.iov_len, - gf_crypt_mt_data); - - if (local->vec.iov_base == NULL) { - gf_log(this->name, GF_LOG_WARNING, - "Failed to calloc head block for prune"); - local->op_ret = -1; - local->op_errno = ENOMEM; - goto put_one_call; - } - for (i = 0; i < count; i++) { - to_copy = vec[i].iov_len; - if (to_copy > local->vec.iov_len - copied) - to_copy = local->vec.iov_len - copied; - - memcpy((char *)local->vec.iov_base + copied, - vec[i].iov_base, - to_copy); - copied += to_copy; - if (copied == local->vec.iov_len) - break; - } - /* - * perform prune with aligned offset - * (i.e. at this step we prune a bit - * more then it is needed - */ - STACK_WIND(frame, - prune_submit_file_tail, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, - local->fd, - conf->aligned_offset, - local->xdata); - return 0; - put_one_call: - put_one_call_ftruncate(frame, this); - return 0; +static int32_t +prune_write(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iovec *vec, int32_t count, + struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) +{ + int32_t i; + size_t to_copy; + size_t copied = 0; + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; + + local->op_ret = op_ret; + local->op_errno = op_errno; + if (op_ret == -1) + goto put_one_call; + + /* + * At first, uptodate head block + */ + if (iov_length(vec, count) < conf->off_in_head) { + gf_log(this->name, GF_LOG_WARNING, + "Failed to uptodate head block for prune"); + local->op_ret = -1; + local->op_errno = EIO; + goto put_one_call; + } + local->vec.iov_len = conf->off_in_head; + local->vec.iov_base = GF_CALLOC(1, local->vec.iov_len, gf_crypt_mt_data); + + if (local->vec.iov_base == NULL) { + gf_log(this->name, GF_LOG_WARNING, + "Failed to calloc head block for prune"); + local->op_ret = -1; + local->op_errno = ENOMEM; + goto put_one_call; + } + for (i = 0; i < count; i++) { + to_copy = vec[i].iov_len; + if (to_copy > local->vec.iov_len - copied) + to_copy = local->vec.iov_len - copied; + + memcpy((char *)local->vec.iov_base + copied, vec[i].iov_base, to_copy); + copied += to_copy; + if (copied == local->vec.iov_len) + break; + } + /* + * perform prune with aligned offset + * (i.e. at this step we prune a bit + * more then it is needed + */ + STACK_WIND(frame, prune_submit_file_tail, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, local->fd, + conf->aligned_offset, local->xdata); + return 0; +put_one_call: + put_one_call_ftruncate(frame, this); + return 0; } /* * Perform a read-prune-write sequence */ -int32_t read_prune_write(call_frame_t *frame, xlator_t *this) -{ - int32_t ret = 0; - dict_t *dict = NULL; - crypt_local_t *local = frame->local; - struct avec_config *conf = &local->data_conf; - struct object_cipher_info *object = &local->info->cinfo; - - set_local_io_params_ftruncate(frame, object); - get_one_call_nolock(frame); - - if ((conf->orig_offset & (object_alg_blksize(object) - 1)) == 0) { - /* - * cblock-aligned prune: - * we don't need read and write components, - * just cut file body - */ - gf_log("crypt", GF_LOG_DEBUG, - "prune without RMW (at offset %llu", - (unsigned long long)conf->orig_offset); - - STACK_WIND(frame, - prune_complete, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, - local->fd, - conf->orig_offset, - local->xdata); - return 0; - } - gf_log("crypt", GF_LOG_DEBUG, - "prune with RMW (at offset %llu", - (unsigned long long)conf->orig_offset); - /* - * We are about to perform the "read" component of the - * read-prune-write sequence. It means that we need to - * read encrypted data from disk and decrypt it. - * So, the crypt translator does STACK_WIND to itself. - * - * Pass current file size to crypt_readv() - - */ - dict = dict_new(); - if (!dict) { - gf_log("crypt", GF_LOG_WARNING, "Can not alloc dict"); - ret = ENOMEM; - goto exit; - } - ret = dict_set(dict, - FSIZE_XATTR_PREFIX, - data_from_uint64(local->cur_file_size)); - if (ret) { - gf_log("crypt", GF_LOG_WARNING, "Can not set dict"); - goto exit; - } - STACK_WIND(frame, - prune_write, - this, - this->fops->readv, /* crypt_readv */ - local->fd, - get_atom_size(object), /* bytes to read */ - conf->aligned_offset, /* offset to read from */ - 0, - dict); - exit: - if (dict) - dict_unref(dict); - return ret; +int32_t +read_prune_write(call_frame_t *frame, xlator_t *this) +{ + int32_t ret = 0; + dict_t *dict = NULL; + crypt_local_t *local = frame->local; + struct avec_config *conf = &local->data_conf; + struct object_cipher_info *object = &local->info->cinfo; + + set_local_io_params_ftruncate(frame, object); + get_one_call_nolock(frame); + + if ((conf->orig_offset & (object_alg_blksize(object) - 1)) == 0) { + /* + * cblock-aligned prune: + * we don't need read and write components, + * just cut file body + */ + gf_log("crypt", GF_LOG_DEBUG, "prune without RMW (at offset %llu", + (unsigned long long)conf->orig_offset); + + STACK_WIND(frame, prune_complete, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, local->fd, + conf->orig_offset, local->xdata); + return 0; + } + gf_log("crypt", GF_LOG_DEBUG, "prune with RMW (at offset %llu", + (unsigned long long)conf->orig_offset); + /* + * We are about to perform the "read" component of the + * read-prune-write sequence. It means that we need to + * read encrypted data from disk and decrypt it. + * So, the crypt translator does STACK_WIND to itself. + * + * Pass current file size to crypt_readv() + + */ + dict = dict_new(); + if (!dict) { + gf_log("crypt", GF_LOG_WARNING, "Can not alloc dict"); + ret = ENOMEM; + goto exit; + } + ret = dict_set(dict, FSIZE_XATTR_PREFIX, + data_from_uint64(local->cur_file_size)); + if (ret) { + gf_log("crypt", GF_LOG_WARNING, "Can not set dict"); + goto exit; + } + STACK_WIND(frame, prune_write, this, this->fops->readv, /* crypt_readv */ + local->fd, get_atom_size(object), /* bytes to read */ + conf->aligned_offset, /* offset to read from */ + 0, dict); +exit: + if (dict) + dict_unref(dict); + return ret; } /* @@ -1539,159 +1401,135 @@ int32_t read_prune_write(call_frame_t *frame, xlator_t *this) * 2) perform cblock-aligned prune * 3) issue a write request for the end-of-file */ -int32_t prune_file(call_frame_t *frame, xlator_t *this, uint64_t offset) -{ - int32_t ret; - - ret = prepare_for_prune(frame, this, offset); - if (ret) - return ret; - return read_prune_write(frame, this); -} - -int32_t expand_file(call_frame_t *frame, xlator_t *this, - uint64_t offset) -{ - int32_t ret; - crypt_local_t *local = frame->local; - - ret = prepare_for_submit_hole(frame, this, - local->old_file_size, - offset - local->old_file_size); - if (ret) - return ret; - submit_hole(frame, this); - return 0; -} - -static int32_t ftruncate_trivial_completion(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - dict_t *dict) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - local->prebuf = *buf; - local->postbuf = *buf; - - local->prebuf.ia_size = local->cur_file_size; - local->postbuf.ia_size = local->cur_file_size; - - get_one_call(frame); - put_one_call_ftruncate(frame, this); - return 0; -} - -static int32_t do_ftruncate(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict, - dict_t *xdata) -{ - data_t *data; - crypt_local_t *local = frame->local; - - if (op_ret) - goto error; - /* - * extract regular file size - */ - data = dict_get(dict, FSIZE_XATTR_PREFIX); - if (!data) { - gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); - op_errno = EIO; - goto error; - } - local->old_file_size = local->cur_file_size = data_to_uint64(data); - - if (local->data_conf.orig_offset == local->cur_file_size) { +int32_t +prune_file(call_frame_t *frame, xlator_t *this, uint64_t offset) +{ + int32_t ret; + + ret = prepare_for_prune(frame, this, offset); + if (ret) + return ret; + return read_prune_write(frame, this); +} + +int32_t +expand_file(call_frame_t *frame, xlator_t *this, uint64_t offset) +{ + int32_t ret; + crypt_local_t *local = frame->local; + + ret = prepare_for_submit_hole(frame, this, local->old_file_size, + offset - local->old_file_size); + if (ret) + return ret; + submit_hole(frame, this); + return 0; +} + +static int32_t +ftruncate_trivial_completion(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *dict) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + local->prebuf = *buf; + local->postbuf = *buf; + + local->prebuf.ia_size = local->cur_file_size; + local->postbuf.ia_size = local->cur_file_size; + + get_one_call(frame); + put_one_call_ftruncate(frame, this); + return 0; +} + +static int32_t +do_ftruncate(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + data_t *data; + crypt_local_t *local = frame->local; + + if (op_ret) + goto error; + /* + * extract regular file size + */ + data = dict_get(dict, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + op_errno = EIO; + goto error; + } + local->old_file_size = local->cur_file_size = data_to_uint64(data); + + if (local->data_conf.orig_offset == local->cur_file_size) { #if DEBUG_CRYPT - gf_log("crypt", GF_LOG_DEBUG, - "trivial ftruncate (current file size %llu)", - (unsigned long long)local->cur_file_size); + gf_log("crypt", GF_LOG_DEBUG, + "trivial ftruncate (current file size %llu)", + (unsigned long long)local->cur_file_size); #endif - goto trivial; - } - else if (local->data_conf.orig_offset < local->cur_file_size) { + goto trivial; + } else if (local->data_conf.orig_offset < local->cur_file_size) { #if DEBUG_CRYPT - gf_log("crypt", GF_LOG_DEBUG, "prune from %llu to %llu", - (unsigned long long)local->cur_file_size, - (unsigned long long)local->data_conf.orig_offset); + gf_log("crypt", GF_LOG_DEBUG, "prune from %llu to %llu", + (unsigned long long)local->cur_file_size, + (unsigned long long)local->data_conf.orig_offset); #endif - op_errno = prune_file(frame, - this, - local->data_conf.orig_offset); - } - else { + op_errno = prune_file(frame, this, local->data_conf.orig_offset); + } else { #if DEBUG_CRYPT - gf_log("crypt", GF_LOG_DEBUG, "expand from %llu to %llu", - (unsigned long long)local->cur_file_size, - (unsigned long long)local->data_conf.orig_offset); + gf_log("crypt", GF_LOG_DEBUG, "expand from %llu to %llu", + (unsigned long long)local->cur_file_size, + (unsigned long long)local->data_conf.orig_offset); #endif - op_errno = expand_file(frame, - this, - local->data_conf.orig_offset); - } - if (op_errno) - goto error; - return 0; - trivial: - STACK_WIND(frame, - ftruncate_trivial_completion, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, - local->fd, - NULL); - return 0; - error: - /* - * finish with ftruncate - */ - local->op_ret = -1; - local->op_errno = op_errno; - - get_one_call_nolock(frame); - put_one_call_ftruncate(frame, this); - return 0; -} - -static int32_t crypt_ftruncate_finodelk_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0) - goto error; - /* - * An access has been granted, - * retrieve file size first - */ - STACK_WIND(frame, - do_ftruncate, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - local->fd, - FSIZE_XATTR_PREFIX, - NULL); - return 0; - error: - get_one_call_nolock(frame); - put_one_call_ftruncate(frame, this); - return 0; + op_errno = expand_file(frame, this, local->data_conf.orig_offset); + } + if (op_errno) + goto error; + return 0; +trivial: + STACK_WIND(frame, ftruncate_trivial_completion, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, local->fd, NULL); + return 0; +error: + /* + * finish with ftruncate + */ + local->op_ret = -1; + local->op_errno = op_errno; + + get_one_call_nolock(frame); + put_one_call_ftruncate(frame, this); + return 0; +} + +static int32_t +crypt_ftruncate_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) + goto error; + /* + * An access has been granted, + * retrieve file size first + */ + STACK_WIND(frame, do_ftruncate, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, local->fd, + FSIZE_XATTR_PREFIX, NULL); + return 0; +error: + get_one_call_nolock(frame); + put_one_call_ftruncate(frame, this); + return 0; } /* @@ -1699,1612 +1537,1316 @@ static int32_t crypt_ftruncate_finodelk_cbk(call_frame_t *frame, * . receive file size; * . expand or prune file. */ -static int32_t crypt_ftruncate(call_frame_t *frame, - xlator_t *this, - fd_t *fd, - off_t offset, - dict_t *xdata) -{ - int32_t ret; - crypt_local_t *local; - struct crypt_inode_info *info; - struct gf_flock lock = {0, }; - - local = crypt_alloc_local(frame, this, GF_FOP_FTRUNCATE); - if (!local) { - ret = ENOMEM; - goto error; - } - local->xattr = dict_new(); - if (!local->xattr) { - ret = ENOMEM; - goto error; - } - local->fd = fd_ref(fd); - info = local_get_inode_info(local, this); - if (info == NULL) { - ret = EINVAL; - goto error; - } - if (!object_alg_atomic(&info->cinfo)) { - ret = EINVAL; - goto error; - } - local->data_conf.orig_offset = offset; - if (xdata) - local->xdata = dict_ref(xdata); - - lock.l_len = 0; - lock.l_start = 0; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; +static int32_t +crypt_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata) +{ + int32_t ret; + crypt_local_t *local; + struct crypt_inode_info *info; + struct gf_flock lock = { + 0, + }; + + local = crypt_alloc_local(frame, this, GF_FOP_FTRUNCATE); + if (!local) { + ret = ENOMEM; + goto error; + } + local->xattr = dict_new(); + if (!local->xattr) { + ret = ENOMEM; + goto error; + } + local->fd = fd_ref(fd); + info = local_get_inode_info(local, this); + if (info == NULL) { + ret = EINVAL; + goto error; + } + if (!object_alg_atomic(&info->cinfo)) { + ret = EINVAL; + goto error; + } + local->data_conf.orig_offset = offset; + if (xdata) + local->xdata = dict_ref(xdata); + + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND(frame, crypt_ftruncate_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, fd, F_SETLKW, + &lock, NULL); + return 0; +error: + if (local && local->fd) + fd_unref(fd); + if (local && local->xdata) + dict_unref(xdata); + if (local && local->xattr) + dict_unref(local->xattr); + if (local && local->info) + free_inode_info(local->info); - STACK_WIND(frame, - crypt_ftruncate_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - fd, - F_SETLKW, - &lock, - NULL); - return 0; - error: - if (local && local->fd) - fd_unref(fd); - if (local && local->xdata) - dict_unref(xdata); - if (local && local->xattr) - dict_unref(local->xattr); - if (local && local->info) - free_inode_info(local->info); - - CRYPT_STACK_UNWIND(ftruncate, frame, -1, ret, NULL, NULL, NULL); - return 0; + CRYPT_STACK_UNWIND(ftruncate, frame, -1, ret, NULL, NULL, NULL); + return 0; } /* ->flush_cbk() */ -int32_t truncate_end(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) +int32_t +truncate_end(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) { - crypt_local_t *local = frame->local; + crypt_local_t *local = frame->local; - CRYPT_STACK_UNWIND(truncate, - frame, - op_ret, - op_errno, - &local->prebuf, - &local->postbuf, - local->xdata); - return 0; + CRYPT_STACK_UNWIND(truncate, frame, op_ret, op_errno, &local->prebuf, + &local->postbuf, local->xdata); + return 0; } /* ftruncate_cbk() */ -int32_t truncate_flush(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *prebuf, - struct iatt *postbuf, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - fd_t *fd = local->fd; - local->prebuf = *prebuf; - local->postbuf = *postbuf; - - STACK_WIND(frame, - truncate_end, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, - fd, - NULL); - fd_unref(fd); - return 0; +int32_t +truncate_flush(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + fd_t *fd = local->fd; + local->prebuf = *prebuf; + local->postbuf = *postbuf; + + STACK_WIND(frame, truncate_end, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, fd, NULL); + fd_unref(fd); + return 0; } /* * is called as ->open_cbk() */ -static int32_t truncate_begin(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) { - fd_unref(fd); - CRYPT_STACK_UNWIND(truncate, - frame, - op_ret, - op_errno, NULL, NULL, NULL); - return 0; - } else { - fd_bind (fd); - } - /* - * crypt_truncate() is implemented via crypt_ftruncate(), - * so the crypt xlator does STACK_WIND to itself here - */ - STACK_WIND(frame, - truncate_flush, - this, - this->fops->ftruncate, /* crypt_ftruncate */ - fd, - local->offset, - NULL); - return 0; +static int32_t +truncate_begin(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) { + fd_unref(fd); + CRYPT_STACK_UNWIND(truncate, frame, op_ret, op_errno, NULL, NULL, NULL); + return 0; + } else { + fd_bind(fd); + } + /* + * crypt_truncate() is implemented via crypt_ftruncate(), + * so the crypt xlator does STACK_WIND to itself here + */ + STACK_WIND(frame, truncate_flush, this, + this->fops->ftruncate, /* crypt_ftruncate */ + fd, local->offset, NULL); + return 0; } /* * crypt_truncate() is implemented via crypt_ftruncate() as a * sequence crypt_open() - crypt_ftruncate() - truncate_flush() */ -int32_t crypt_truncate(call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset, - dict_t *xdata) +int32_t +crypt_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { - fd_t *fd; - crypt_local_t *local; + fd_t *fd; + crypt_local_t *local; #if DEBUG_CRYPT - gf_log(this->name, GF_LOG_DEBUG, - "truncate file %s at offset %llu", - loc->path, (unsigned long long)offset); + gf_log(this->name, GF_LOG_DEBUG, "truncate file %s at offset %llu", + loc->path, (unsigned long long)offset); #endif - local = crypt_alloc_local(frame, this, GF_FOP_TRUNCATE); - if (!local) - goto error; - - fd = fd_create(loc->inode, frame->root->pid); - if (!fd) { - gf_log(this->name, GF_LOG_ERROR, "Can not create fd"); - goto error; - } - local->fd = fd; - local->offset = offset; - local->xdata = xdata; - STACK_WIND(frame, - truncate_begin, - this, - this->fops->open, /* crypt_open() */ - loc, - O_RDWR, - fd, - NULL); - return 0; - error: - CRYPT_STACK_UNWIND(truncate, frame, -1, EINVAL, NULL, NULL, NULL); - return 0; -} - -end_writeback_handler_t dispatch_end_writeback(glusterfs_fop_t fop) -{ - switch (fop) { - case GF_FOP_WRITE: - return end_writeback_writev; - case GF_FOP_FTRUNCATE: - return end_writeback_ftruncate; - default: - gf_log("crypt", GF_LOG_WARNING, "Bad wb operation %d", fop); - return NULL; - } + local = crypt_alloc_local(frame, this, GF_FOP_TRUNCATE); + if (!local) + goto error; + + fd = fd_create(loc->inode, frame->root->pid); + if (!fd) { + gf_log(this->name, GF_LOG_ERROR, "Can not create fd"); + goto error; + } + local->fd = fd; + local->offset = offset; + local->xdata = xdata; + STACK_WIND(frame, truncate_begin, this, this->fops->open, /* crypt_open() */ + loc, O_RDWR, fd, NULL); + return 0; +error: + CRYPT_STACK_UNWIND(truncate, frame, -1, EINVAL, NULL, NULL, NULL); + return 0; +} + +end_writeback_handler_t +dispatch_end_writeback(glusterfs_fop_t fop) +{ + switch (fop) { + case GF_FOP_WRITE: + return end_writeback_writev; + case GF_FOP_FTRUNCATE: + return end_writeback_ftruncate; + default: + gf_log("crypt", GF_LOG_WARNING, "Bad wb operation %d", fop); + return NULL; + } } /* * true, if the caller needs metadata string */ -static int32_t is_custom_mtd(dict_t *xdata) +static int32_t +is_custom_mtd(dict_t *xdata) { - data_t *data; - uint32_t flags; + data_t *data; + uint32_t flags; - if (!xdata) - return 0; + if (!xdata) + return 0; - data = dict_get(xdata, MSGFLAGS_PREFIX); - if (!data) - return 0; - if (data->len != sizeof(uint32_t)) { - gf_log("crypt", GF_LOG_WARNING, - "Bad msgflags size (%d)", data->len); - return -1; - } - flags = *((uint32_t *)data->data); - return msgflags_check_mtd_lock(&flags); + data = dict_get(xdata, MSGFLAGS_PREFIX); + if (!data) + return 0; + if (data->len != sizeof(uint32_t)) { + gf_log("crypt", GF_LOG_WARNING, "Bad msgflags size (%d)", data->len); + return -1; + } + flags = *((uint32_t *)data->data); + return msgflags_check_mtd_lock(&flags); } -static int32_t crypt_open_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) +static int32_t +crypt_open_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - crypt_local_t *local = frame->local; + crypt_local_t *local = frame->local; - local->op_ret = op_ret; - local->op_errno = op_errno; - if (op_ret < 0) - gf_log(this->name, GF_LOG_WARNING, "mtd unlock failed (%d)", - op_errno); - put_one_call_open(frame); - return 0; + local->op_ret = op_ret; + local->op_errno = op_errno; + if (op_ret < 0) + gf_log(this->name, GF_LOG_WARNING, "mtd unlock failed (%d)", op_errno); + put_one_call_open(frame); + return 0; } -static void crypt_open_tail(call_frame_t *frame, xlator_t *this) +static void +crypt_open_tail(call_frame_t *frame, xlator_t *this) { - struct gf_flock lock = {0, }; - crypt_local_t *local = frame->local; + struct gf_flock lock = { + 0, + }; + crypt_local_t *local = frame->local; - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; - STACK_WIND(frame, - crypt_open_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); + STACK_WIND(frame, crypt_open_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); } /* * load private inode info at open time * called as ->fgetxattr_cbk() */ -static int load_mtd_open(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict, - dict_t *xdata) -{ - int32_t ret; - gf_boolean_t upload_info; - data_t *mtd; - uint64_t value = 0; - struct crypt_inode_info *info; - crypt_local_t *local = frame->local; - crypt_private_t *priv = this->private; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (local->fd->inode->ia_type == IA_IFLNK) - goto exit; - if (op_ret < 0) - goto exit; - /* - * first, check for cached info - */ - ret = inode_ctx_get(local->fd->inode, this, &value); - if (ret != -1) { - info = (struct crypt_inode_info *)(long)value; - if (info == NULL) { - gf_log(this->name, GF_LOG_WARNING, - "Inode info expected, but not found"); - local->op_ret = -1; - local->op_errno = EIO; - goto exit; - } - /* - * info has been found in the cache - */ - upload_info = _gf_false; - } - else { - /* - * info hasn't been found in the cache. - */ - info = alloc_inode_info(local, local->loc); - if (!info) { - local->op_ret = -1; - local->op_errno = ENOMEM; - goto exit; - } - init_inode_info_head(info, local->fd); - upload_info = _gf_true; - } - /* - * extract metadata - */ - mtd = dict_get(dict, CRYPTO_FORMAT_PREFIX); - if (!mtd) { - local->op_ret = -1; - local->op_errno = ENOENT; - gf_log (this->name, GF_LOG_WARNING, - "Format string wasn't found"); - goto exit; - } - /* - * authenticate metadata against the path - */ - ret = open_format((unsigned char *)mtd->data, - mtd->len, - local->loc, - info, - get_master_cinfo(priv), - local, - upload_info); - if (ret) { - local->op_ret = -1; - local->op_errno = ret; - goto exit; - } - if (upload_info) { - ret = init_inode_info_tail(info, get_master_cinfo(priv)); - if (ret) { - local->op_ret = -1; - local->op_errno = ret; - goto exit; - } - ret = inode_ctx_put(local->fd->inode, - this, (uint64_t)(long)info); - if (ret == -1) { - local->op_ret = -1; - local->op_errno = EIO; - goto exit; - } - } - if (local->custom_mtd) { - /* - * pass the metadata string to the customer - */ - ret = dict_set_static_bin(local->xdata, - CRYPTO_FORMAT_PREFIX, - mtd->data, - mtd->len); - if (ret) { - local->op_ret = -1; - local->op_errno = ret; - goto exit; - } - } - exit: - if (!local->custom_mtd) - crypt_open_tail(frame, this); - else - put_one_call_open(frame); - return 0; -} - -static int32_t crypt_open_finodelk_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0) { - gf_log(this->name, GF_LOG_WARNING, "finodelk (LOCK) failed"); - goto exit; - } - STACK_WIND(frame, - load_mtd_open, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - local->fd, - CRYPTO_FORMAT_PREFIX, - NULL); - return 0; - exit: - put_one_call_open(frame); - return 0; +static int +load_mtd_open(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + int32_t ret; + gf_boolean_t upload_info; + data_t *mtd; + uint64_t value = 0; + struct crypt_inode_info *info; + crypt_local_t *local = frame->local; + crypt_private_t *priv = this->private; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (local->fd->inode->ia_type == IA_IFLNK) + goto exit; + if (op_ret < 0) + goto exit; + /* + * first, check for cached info + */ + ret = inode_ctx_get(local->fd->inode, this, &value); + if (ret != -1) { + info = (struct crypt_inode_info *)(long)value; + if (info == NULL) { + gf_log(this->name, GF_LOG_WARNING, + "Inode info expected, but not found"); + local->op_ret = -1; + local->op_errno = EIO; + goto exit; + } + /* + * info has been found in the cache + */ + upload_info = _gf_false; + } else { + /* + * info hasn't been found in the cache. + */ + info = alloc_inode_info(local, local->loc); + if (!info) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto exit; + } + init_inode_info_head(info, local->fd); + upload_info = _gf_true; + } + /* + * extract metadata + */ + mtd = dict_get(dict, CRYPTO_FORMAT_PREFIX); + if (!mtd) { + local->op_ret = -1; + local->op_errno = ENOENT; + gf_log(this->name, GF_LOG_WARNING, "Format string wasn't found"); + goto exit; + } + /* + * authenticate metadata against the path + */ + ret = open_format((unsigned char *)mtd->data, mtd->len, local->loc, info, + get_master_cinfo(priv), local, upload_info); + if (ret) { + local->op_ret = -1; + local->op_errno = ret; + goto exit; + } + if (upload_info) { + ret = init_inode_info_tail(info, get_master_cinfo(priv)); + if (ret) { + local->op_ret = -1; + local->op_errno = ret; + goto exit; + } + ret = inode_ctx_put(local->fd->inode, this, (uint64_t)(long)info); + if (ret == -1) { + local->op_ret = -1; + local->op_errno = EIO; + goto exit; + } + } + if (local->custom_mtd) { + /* + * pass the metadata string to the customer + */ + ret = dict_set_static_bin(local->xdata, CRYPTO_FORMAT_PREFIX, mtd->data, + mtd->len); + if (ret) { + local->op_ret = -1; + local->op_errno = ret; + goto exit; + } + } +exit: + if (!local->custom_mtd) + crypt_open_tail(frame, this); + else + put_one_call_open(frame); + return 0; +} + +static int32_t +crypt_open_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) { + gf_log(this->name, GF_LOG_WARNING, "finodelk (LOCK) failed"); + goto exit; + } + STACK_WIND(frame, load_mtd_open, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, local->fd, + CRYPTO_FORMAT_PREFIX, NULL); + return 0; +exit: + put_one_call_open(frame); + return 0; } /* * verify metadata against the specified pathname */ -static int32_t crypt_open_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - dict_t *xdata) -{ - struct gf_flock lock = {0, }; - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (local->fd->inode->ia_type == IA_IFLNK) - goto exit; - if (op_ret < 0) - goto exit; - if (xdata) - local->xdata = dict_ref(xdata); - else if (local->custom_mtd){ - local->xdata = dict_new(); - if (!local->xdata) { - local->op_ret = -1; - local->op_errno = ENOMEM; - gf_log ("crypt", GF_LOG_ERROR, - "Can not get new dict for mtd string"); - goto exit; - } - } - lock.l_len = 0; - lock.l_start = 0; - lock.l_type = local->custom_mtd ? F_WRLCK : F_RDLCK; - lock.l_whence = SEEK_SET; +static int32_t +crypt_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + struct gf_flock lock = { + 0, + }; + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (local->fd->inode->ia_type == IA_IFLNK) + goto exit; + if (op_ret < 0) + goto exit; + if (xdata) + local->xdata = dict_ref(xdata); + else if (local->custom_mtd) { + local->xdata = dict_new(); + if (!local->xdata) { + local->op_ret = -1; + local->op_errno = ENOMEM; + gf_log("crypt", GF_LOG_ERROR, + "Can not get new dict for mtd string"); + goto exit; + } + } + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = local->custom_mtd ? F_WRLCK : F_RDLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND(frame, crypt_open_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, fd, F_SETLKW, + &lock, NULL); + return 0; +exit: + put_one_call_open(frame); + return 0; +} + +static int32_t +crypt_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata) +{ + int32_t ret = ENOMEM; + crypt_local_t *local; + + local = crypt_alloc_local(frame, this, GF_FOP_OPEN); + if (!local) + goto error; + local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!local->loc) { + ret = ENOMEM; + goto error; + } + ret = loc_copy(local->loc, loc); + if (ret) { + GF_FREE(local->loc); + ret = ENOMEM; + goto error; + } + local->fd = fd_ref(fd); + + ret = is_custom_mtd(xdata); + if (ret < 0) { + loc_wipe(local->loc); + GF_FREE(local->loc); + ret = EINVAL; + goto error; + } + local->custom_mtd = ret; + + if ((flags & O_ACCMODE) == O_WRONLY) + /* + * we can't open O_WRONLY, because + * we need to do read-modify-write + */ + flags = (flags & ~O_ACCMODE) | O_RDWR; + /* + * Make sure that out translated offsets + * and counts won't be ignored + */ + flags &= ~O_APPEND; + get_one_call_nolock(frame); + STACK_WIND(frame, crypt_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); + return 0; +error: + CRYPT_STACK_UNWIND(open, frame, -1, ret, NULL, NULL); + return 0; +} - STACK_WIND(frame, - crypt_open_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - fd, - F_SETLKW, - &lock, - NULL); - return 0; - exit: - put_one_call_open(frame); - return 0; -} - -static int32_t crypt_open(call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - fd_t *fd, - dict_t *xdata) -{ - int32_t ret = ENOMEM; - crypt_local_t *local; - - local = crypt_alloc_local(frame, this, GF_FOP_OPEN); - if (!local) - goto error; - local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!local->loc) { - ret = ENOMEM; - goto error; - } - ret = loc_copy(local->loc, loc); - if (ret) { - GF_FREE(local->loc); - ret = ENOMEM; - goto error; - } - local->fd = fd_ref(fd); - - ret = is_custom_mtd(xdata); - if (ret < 0) { - loc_wipe(local->loc); - GF_FREE(local->loc); - ret = EINVAL; - goto error; - } - local->custom_mtd = ret; - - if ((flags & O_ACCMODE) == O_WRONLY) - /* - * we can't open O_WRONLY, because - * we need to do read-modify-write - */ - flags = (flags & ~O_ACCMODE) | O_RDWR; - /* - * Make sure that out translated offsets - * and counts won't be ignored - */ - flags &= ~O_APPEND; - get_one_call_nolock(frame); - STACK_WIND(frame, - crypt_open_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->open, - loc, - flags, - fd, - xdata); - return 0; - error: - CRYPT_STACK_UNWIND(open, - frame, - -1, - ret, - NULL, - NULL); - return 0; -} - -static int32_t init_inode_info_tail(struct crypt_inode_info *info, - struct master_cipher_info *master) -{ - int32_t ret; - struct object_cipher_info *object = &info->cinfo; +static int32_t +init_inode_info_tail(struct crypt_inode_info *info, + struct master_cipher_info *master) +{ + int32_t ret; + struct object_cipher_info *object = &info->cinfo; #if DEBUG_CRYPT - gf_log("crypt", GF_LOG_DEBUG, "Init inode info for object %s", - uuid_utoa(info->oid)); + gf_log("crypt", GF_LOG_DEBUG, "Init inode info for object %s", + uuid_utoa(info->oid)); #endif - ret = data_cipher_algs[object->o_alg][object->o_mode].set_private(info, - master); - if (ret) { - gf_log("crypt", GF_LOG_ERROR, "Set private info failed"); - return ret; - } - return 0; + ret = data_cipher_algs[object->o_alg][object->o_mode].set_private(info, + master); + if (ret) { + gf_log("crypt", GF_LOG_ERROR, "Set private info failed"); + return ret; + } + return 0; } /* * Init inode info at ->create() time */ -static void init_inode_info_create(struct crypt_inode_info *info, - struct master_cipher_info *master, - data_t *data) -{ - struct object_cipher_info *object; - - info->nr_minor = CRYPT_XLATOR_ID; - memcpy(info->oid, data->data, data->len); - - object = &info->cinfo; - - object->o_alg = master->m_alg; - object->o_mode = master->m_mode; - object->o_block_bits = master->m_block_bits; - object->o_dkey_size = master->m_dkey_size; -} - -static void init_inode_info_head(struct crypt_inode_info *info, fd_t *fd) -{ - memcpy(info->oid, fd->inode->gfid, sizeof(uuid_t)); -} - -static int32_t crypt_create_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) -{ - crypt_private_t *priv = this->private; - crypt_local_t *local = frame->local; - struct crypt_inode_info *info = local->info; - fd_t *local_fd = local->fd; - dict_t *local_xdata = local->xdata; - inode_t *local_inode = local->inode; - - if (op_ret < 0) { - free_inode_info(info); - goto unwind; - } - op_errno = init_inode_info_tail(info, get_master_cinfo(priv)); - if (op_errno) { - op_ret = -1; - free_inode_info(info); - goto unwind; - } - /* - * FIXME: drop major subversion number - */ - op_ret = inode_ctx_put(local->fd->inode, this, (uint64_t)(long)info); - if (op_ret == -1) { - op_errno = EIO; - free_inode_info(info); - goto unwind; - } - unwind: - free_format(local); - CRYPT_STACK_UNWIND(create, - frame, - op_ret, - op_errno, - local_fd, - local_inode, - &local->buf, - &local->prebuf, - &local->postbuf, - local_xdata); - fd_unref(local_fd); - inode_unref(local_inode); - if (local_xdata) - dict_unref(local_xdata); - return 0; -} - -static int crypt_create_tail(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - struct gf_flock lock = {0, }; - crypt_local_t *local = frame->local; - fd_t *local_fd = local->fd; - dict_t *local_xdata = local->xdata; - inode_t *local_inode = local->inode; - - dict_unref(local->xattr); - - if (op_ret < 0) - goto error; - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - - STACK_WIND(frame, - crypt_create_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - return 0; - error: - free_inode_info(local->info); - free_format(local); - - CRYPT_STACK_UNWIND(create, - frame, - op_ret, - op_errno, - local_fd, - local_inode, - &local->buf, - &local->prebuf, - &local->postbuf, - local_xdata); - - fd_unref(local_fd); - inode_unref(local_inode); - if (local_xdata) - dict_unref(local_xdata); - return 0; -} - -static int32_t crypt_create_finodelk_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - struct crypt_inode_info *info = local->info; - - if (op_ret < 0) - goto error; - - STACK_WIND(frame, - crypt_create_tail, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, - local->fd, - local->xattr, /* CRYPTO_FORMAT_PREFIX */ - 0, - NULL); - return 0; - error: - free_inode_info(info); - free_format(local); - fd_unref(local->fd); - dict_unref(local->xattr); - if (local->xdata) - dict_unref(local->xdata); - - CRYPT_STACK_UNWIND(create, - frame, - op_ret, - op_errno, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - return 0; +static void +init_inode_info_create(struct crypt_inode_info *info, + struct master_cipher_info *master, data_t *data) +{ + struct object_cipher_info *object; + + info->nr_minor = CRYPT_XLATOR_ID; + memcpy(info->oid, data->data, data->len); + + object = &info->cinfo; + + object->o_alg = master->m_alg; + object->o_mode = master->m_mode; + object->o_block_bits = master->m_block_bits; + object->o_dkey_size = master->m_dkey_size; +} + +static void +init_inode_info_head(struct crypt_inode_info *info, fd_t *fd) +{ + memcpy(info->oid, fd->inode->gfid, sizeof(uuid_t)); +} + +static int32_t +crypt_create_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_private_t *priv = this->private; + crypt_local_t *local = frame->local; + struct crypt_inode_info *info = local->info; + fd_t *local_fd = local->fd; + dict_t *local_xdata = local->xdata; + inode_t *local_inode = local->inode; + + if (op_ret < 0) { + free_inode_info(info); + goto unwind; + } + op_errno = init_inode_info_tail(info, get_master_cinfo(priv)); + if (op_errno) { + op_ret = -1; + free_inode_info(info); + goto unwind; + } + /* + * FIXME: drop major subversion number + */ + op_ret = inode_ctx_put(local->fd->inode, this, (uint64_t)(long)info); + if (op_ret == -1) { + op_errno = EIO; + free_inode_info(info); + goto unwind; + } +unwind: + free_format(local); + CRYPT_STACK_UNWIND(create, frame, op_ret, op_errno, local_fd, local_inode, + &local->buf, &local->prebuf, &local->postbuf, + local_xdata); + fd_unref(local_fd); + inode_unref(local_inode); + if (local_xdata) + dict_unref(local_xdata); + return 0; +} + +static int +crypt_create_tail(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct gf_flock lock = { + 0, + }; + crypt_local_t *local = frame->local; + fd_t *local_fd = local->fd; + dict_t *local_xdata = local->xdata; + inode_t *local_inode = local->inode; + + dict_unref(local->xattr); + + if (op_ret < 0) + goto error; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND(frame, crypt_create_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + return 0; +error: + free_inode_info(local->info); + free_format(local); + + CRYPT_STACK_UNWIND(create, frame, op_ret, op_errno, local_fd, local_inode, + &local->buf, &local->prebuf, &local->postbuf, + local_xdata); + + fd_unref(local_fd); + inode_unref(local_inode); + if (local_xdata) + dict_unref(local_xdata); + return 0; +} + +static int32_t +crypt_create_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + struct crypt_inode_info *info = local->info; + + if (op_ret < 0) + goto error; + + STACK_WIND(frame, crypt_create_tail, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, local->fd, + local->xattr, /* CRYPTO_FORMAT_PREFIX */ + 0, NULL); + return 0; +error: + free_inode_info(info); + free_format(local); + fd_unref(local->fd); + dict_unref(local->xattr); + if (local->xdata) + dict_unref(local->xdata); + + CRYPT_STACK_UNWIND(create, frame, op_ret, op_errno, NULL, NULL, NULL, NULL, + NULL, NULL); + return 0; } /* * Create and store crypt-specific format on disk; * Populate cache with private inode info */ -static int32_t crypt_create_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent, - dict_t *xdata) -{ - struct gf_flock lock = {0, }; - crypt_local_t *local = frame->local; - struct crypt_inode_info *info = local->info; - - if (op_ret < 0) - goto error; - if (xdata) - local->xdata = dict_ref(xdata); - local->inode = inode_ref(inode); - local->buf = *buf; - local->prebuf = *preparent; - local->postbuf = *postparent; - - lock.l_len = 0; - lock.l_start = 0; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - - STACK_WIND(frame, - crypt_create_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - return 0; - error: - free_inode_info(info); - free_format(local); - fd_unref(local->fd); - dict_unref(local->xattr); - - CRYPT_STACK_UNWIND(create, - frame, - op_ret, - op_errno, - NULL, NULL, NULL, - NULL, NULL, NULL); - return 0; -} - -static int32_t crypt_create(call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - mode_t mode, - mode_t umask, - fd_t *fd, - dict_t *xdata) -{ - int ret; - data_t *data; - crypt_local_t *local; - crypt_private_t *priv; - struct master_cipher_info *master; - struct crypt_inode_info *info; - - priv = this->private; - master = get_master_cinfo(priv); - - if (master_alg_atomic(master)) { - /* - * We can't open O_WRONLY, because we - * need to do read-modify-write. - */ - if ((flags & O_ACCMODE) == O_WRONLY) - flags = (flags & ~O_ACCMODE) | O_RDWR; - /* - * Make sure that out translated offsets - * and counts won't be ignored - */ - flags &= ~O_APPEND; - } - local = crypt_alloc_local(frame, this, GF_FOP_CREATE); - if (!local) { - ret = ENOMEM; - goto error; - } - data = dict_get(xdata, "gfid-req"); - if (!data) { - ret = EINVAL; - gf_log("crypt", GF_LOG_WARNING, "gfid not found"); - goto error; - } - if (data->len != sizeof(uuid_t)) { - ret = EINVAL; - gf_log("crypt", GF_LOG_WARNING, - "bad gfid size (%d), should be %d", - (int)data->len, (int)sizeof(uuid_t)); - goto error; - } - info = alloc_inode_info(local, loc); - if (!info){ - ret = ENOMEM; - goto error; - } - /* - * NOTE: - * format has to be created BEFORE - * proceeding to the untrusted server - */ - ret = alloc_format_create(local); - if (ret) { - free_inode_info(info); - goto error; - } - init_inode_info_create(info, master, data); - - ret = create_format(local->format, - loc, - info, - master); - if (ret) { - free_inode_info(info); - goto error; - } - local->xattr = dict_new(); - if (!local->xattr) { - free_inode_info(info); - free_format(local); - goto error; - } - ret = dict_set_static_bin(local->xattr, - CRYPTO_FORMAT_PREFIX, - local->format, - new_format_size()); - if (ret) { - dict_unref(local->xattr); - free_inode_info(info); - free_format(local); - ret = EINVAL; - goto error; - } - ret = dict_set(local->xattr, FSIZE_XATTR_PREFIX, data_from_uint64(0)); - if (ret) { - dict_unref(local->xattr); - free_inode_info(info); - free_format(local); - ret = ENOMEM; - goto error; - } - local->fd = fd_ref(fd); - - STACK_WIND(frame, - crypt_create_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, - loc, - flags, - mode, - umask, - fd, - xdata); - return 0; - error: - gf_log("crypt", GF_LOG_WARNING, "can not create file"); - CRYPT_STACK_UNWIND(create, - frame, - -1, - ret, - NULL, NULL, NULL, - NULL, NULL, NULL); - return 0; +static int32_t +crypt_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct gf_flock lock = { + 0, + }; + crypt_local_t *local = frame->local; + struct crypt_inode_info *info = local->info; + + if (op_ret < 0) + goto error; + if (xdata) + local->xdata = dict_ref(xdata); + local->inode = inode_ref(inode); + local->buf = *buf; + local->prebuf = *preparent; + local->postbuf = *postparent; + + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND(frame, crypt_create_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + return 0; +error: + free_inode_info(info); + free_format(local); + fd_unref(local->fd); + dict_unref(local->xattr); + + CRYPT_STACK_UNWIND(create, frame, op_ret, op_errno, NULL, NULL, NULL, NULL, + NULL, NULL); + return 0; +} + +static int32_t +crypt_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) +{ + int ret; + data_t *data; + crypt_local_t *local; + crypt_private_t *priv; + struct master_cipher_info *master; + struct crypt_inode_info *info; + + priv = this->private; + master = get_master_cinfo(priv); + + if (master_alg_atomic(master)) { + /* + * We can't open O_WRONLY, because we + * need to do read-modify-write. + */ + if ((flags & O_ACCMODE) == O_WRONLY) + flags = (flags & ~O_ACCMODE) | O_RDWR; + /* + * Make sure that out translated offsets + * and counts won't be ignored + */ + flags &= ~O_APPEND; + } + local = crypt_alloc_local(frame, this, GF_FOP_CREATE); + if (!local) { + ret = ENOMEM; + goto error; + } + data = dict_get(xdata, "gfid-req"); + if (!data) { + ret = EINVAL; + gf_log("crypt", GF_LOG_WARNING, "gfid not found"); + goto error; + } + if (data->len != sizeof(uuid_t)) { + ret = EINVAL; + gf_log("crypt", GF_LOG_WARNING, "bad gfid size (%d), should be %d", + (int)data->len, (int)sizeof(uuid_t)); + goto error; + } + info = alloc_inode_info(local, loc); + if (!info) { + ret = ENOMEM; + goto error; + } + /* + * NOTE: + * format has to be created BEFORE + * proceeding to the untrusted server + */ + ret = alloc_format_create(local); + if (ret) { + free_inode_info(info); + goto error; + } + init_inode_info_create(info, master, data); + + ret = create_format(local->format, loc, info, master); + if (ret) { + free_inode_info(info); + goto error; + } + local->xattr = dict_new(); + if (!local->xattr) { + free_inode_info(info); + free_format(local); + goto error; + } + ret = dict_set_static_bin(local->xattr, CRYPTO_FORMAT_PREFIX, local->format, + new_format_size()); + if (ret) { + dict_unref(local->xattr); + free_inode_info(info); + free_format(local); + ret = EINVAL; + goto error; + } + ret = dict_set(local->xattr, FSIZE_XATTR_PREFIX, data_from_uint64(0)); + if (ret) { + dict_unref(local->xattr); + free_inode_info(info); + free_format(local); + ret = ENOMEM; + goto error; + } + local->fd = fd_ref(fd); + + STACK_WIND(frame, crypt_create_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, + xdata); + return 0; +error: + gf_log("crypt", GF_LOG_WARNING, "can not create file"); + CRYPT_STACK_UNWIND(create, frame, -1, ret, NULL, NULL, NULL, NULL, NULL, + NULL); + return 0; } /* * FIXME: this should depends on the version of format string */ -static int32_t filter_crypt_xattr(dict_t *dict, - char *key, data_t *value, void *data) +static int32_t +filter_crypt_xattr(dict_t *dict, char *key, data_t *value, void *data) { - dict_del(dict, key); - return 0; + dict_del(dict, key); + return 0; } -static int32_t crypt_fsetxattr(call_frame_t *frame, - xlator_t *this, - fd_t *fd, - dict_t *dict, - int32_t flags, dict_t *xdata) +static int32_t +crypt_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata) { - dict_foreach_fnmatch(dict, "trusted.glusterfs.crypt*", - filter_crypt_xattr, NULL); - STACK_WIND(frame, - default_fsetxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, - fd, - dict, - flags, - xdata); - return 0; + dict_foreach_fnmatch(dict, "trusted.glusterfs.crypt*", filter_crypt_xattr, + NULL); + STACK_WIND(frame, default_fsetxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); + return 0; } /* * TBD: verify file metadata before wind */ -static int32_t crypt_setxattr(call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags, dict_t *xdata) -{ - dict_foreach_fnmatch(dict, "trusted.glusterfs.crypt*", - filter_crypt_xattr, NULL); - STACK_WIND(frame, - default_setxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, - loc, - dict, - flags, - xdata); - return 0; +static int32_t +crypt_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + dict_foreach_fnmatch(dict, "trusted.glusterfs.crypt*", filter_crypt_xattr, + NULL); + STACK_WIND(frame, default_setxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); + return 0; } /* * called as flush_cbk() */ -static int32_t linkop_end(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - linkop_unwind_handler_t unwind_fn; - unwind_fn = linkop_unwind_dispatch(local->fop); - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret < 0 && - op_errno == ENOENT && - local->loc->inode->ia_type == IA_IFLNK) { - local->op_ret = 0; - local->op_errno = 0; - } - unwind_fn(frame); - return 0; +static int32_t +linkop_end(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + linkop_unwind_handler_t unwind_fn; + unwind_fn = linkop_unwind_dispatch(local->fop); + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0 && op_errno == ENOENT && + local->loc->inode->ia_type == IA_IFLNK) { + local->op_ret = 0; + local->op_errno = 0; + } + unwind_fn(frame); + return 0; } /* * unpin inode on the server */ -static int32_t link_flush(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto error; - if (local->xdata) { - dict_unref(local->xdata); - local->xdata = NULL; - } - if (xdata) - local->xdata = dict_ref(xdata); - local->inode = inode_ref(inode); - local->buf = *buf; - local->prebuf = *preparent; - local->postbuf = *postparent; - - STACK_WIND(frame, - linkop_end, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, - local->fd, - NULL); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - link_unwind(frame); - return 0; -} - -void link_unwind(call_frame_t *frame) -{ - crypt_local_t *local = frame->local; - dict_t *xdata; - dict_t *xattr; - inode_t *inode; - - if (!local) { - CRYPT_STACK_UNWIND(link, - frame, - -1, - ENOMEM, - NULL, - NULL, - NULL, - NULL, - NULL); - return; - } - xdata = local->xdata; - xattr = local->xattr; - inode = local->inode; - - if (local->loc){ - loc_wipe(local->loc); - GF_FREE(local->loc); - } - if (local->newloc) { - loc_wipe(local->newloc); - GF_FREE(local->newloc); - } - if (local->fd) - fd_unref(local->fd); - if (local->format) - GF_FREE(local->format); - - CRYPT_STACK_UNWIND(link, - frame, - local->op_ret, - local->op_errno, - inode, - &local->buf, - &local->prebuf, - &local->postbuf, - xdata); - if (xdata) - dict_unref(xdata); - if (xattr) - dict_unref(xattr); - if (inode) - inode_unref(inode); -} - -void link_wind(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - - STACK_WIND(frame, - link_flush, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, - local->loc, - local->newloc, - local->xdata); +static int32_t +link_flush(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto error; + if (local->xdata) { + dict_unref(local->xdata); + local->xdata = NULL; + } + if (xdata) + local->xdata = dict_ref(xdata); + local->inode = inode_ref(inode); + local->buf = *buf; + local->prebuf = *preparent; + local->postbuf = *postparent; + + STACK_WIND(frame, linkop_end, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, local->fd, NULL); + return 0; +error: + local->op_ret = -1; + local->op_errno = op_errno; + link_unwind(frame); + return 0; +} + +void +link_unwind(call_frame_t *frame) +{ + crypt_local_t *local = frame->local; + dict_t *xdata; + dict_t *xattr; + inode_t *inode; + + if (!local) { + CRYPT_STACK_UNWIND(link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL); + return; + } + xdata = local->xdata; + xattr = local->xattr; + inode = local->inode; + + if (local->loc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + } + if (local->newloc) { + loc_wipe(local->newloc); + GF_FREE(local->newloc); + } + if (local->fd) + fd_unref(local->fd); + if (local->format) + GF_FREE(local->format); + + CRYPT_STACK_UNWIND(link, frame, local->op_ret, local->op_errno, inode, + &local->buf, &local->prebuf, &local->postbuf, xdata); + if (xdata) + dict_unref(xdata); + if (xattr) + dict_unref(xattr); + if (inode) + inode_unref(inode); +} + +void +link_wind(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + + STACK_WIND(frame, link_flush, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, local->loc, local->newloc, + local->xdata); } /* * unlink() */ -static int32_t unlink_flush(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto error; - local->prebuf = *preparent; - local->postbuf = *postparent; - if (local->xdata) { - dict_unref(local->xdata); - local->xdata = NULL; - } - if (xdata) - local->xdata = dict_ref(xdata); - - STACK_WIND(frame, - linkop_end, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, - local->fd, - NULL); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - unlink_unwind(frame); - return 0; -} - -void unlink_unwind(call_frame_t *frame) -{ - crypt_local_t *local = frame->local; - dict_t *xdata; - dict_t *xattr; - - if (!local) { - CRYPT_STACK_UNWIND(unlink, - frame, - -1, - ENOMEM, - NULL, - NULL, - NULL); - return; - } - xdata = local->xdata; - xattr = local->xattr; - if (local->loc){ - loc_wipe(local->loc); - GF_FREE(local->loc); - } - if (local->fd) - fd_unref(local->fd); - if (local->format) - GF_FREE(local->format); - - CRYPT_STACK_UNWIND(unlink, - frame, - local->op_ret, - local->op_errno, - &local->prebuf, - &local->postbuf, - xdata); - if (xdata) - dict_unref(xdata); - if (xattr) - dict_unref(xattr); -} - -void unlink_wind(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - - STACK_WIND(frame, - unlink_flush, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, - local->loc, - local->flags, - local->xdata); -} - -void rename_unwind(call_frame_t *frame) -{ - crypt_local_t *local = frame->local; - dict_t *xdata; - dict_t *xattr; - struct iatt *prenewparent; - struct iatt *postnewparent; - - if (!local) { - CRYPT_STACK_UNWIND(rename, - frame, - -1, - ENOMEM, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - return; - } - xdata = local->xdata; - xattr = local->xattr; - prenewparent = local->prenewparent; - postnewparent = local->postnewparent; - - if (local->loc){ - loc_wipe(local->loc); - GF_FREE(local->loc); - } - if (local->newloc){ - loc_wipe(local->newloc); - GF_FREE(local->newloc); - } - if (local->fd) - fd_unref(local->fd); - if (local->format) - GF_FREE(local->format); - - CRYPT_STACK_UNWIND(rename, - frame, - local->op_ret, - local->op_errno, - &local->buf, - &local->prebuf, - &local->postbuf, - prenewparent, - postnewparent, - xdata); - if (xdata) - dict_unref(xdata); - if (xattr) - dict_unref(xattr); - if (prenewparent) - GF_FREE(prenewparent); - if (postnewparent) - GF_FREE(postnewparent); +static int32_t +unlink_flush(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto error; + local->prebuf = *preparent; + local->postbuf = *postparent; + if (local->xdata) { + dict_unref(local->xdata); + local->xdata = NULL; + } + if (xdata) + local->xdata = dict_ref(xdata); + + STACK_WIND(frame, linkop_end, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, local->fd, NULL); + return 0; +error: + local->op_ret = -1; + local->op_errno = op_errno; + unlink_unwind(frame); + return 0; +} + +void +unlink_unwind(call_frame_t *frame) +{ + crypt_local_t *local = frame->local; + dict_t *xdata; + dict_t *xattr; + + if (!local) { + CRYPT_STACK_UNWIND(unlink, frame, -1, ENOMEM, NULL, NULL, NULL); + return; + } + xdata = local->xdata; + xattr = local->xattr; + if (local->loc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + } + if (local->fd) + fd_unref(local->fd); + if (local->format) + GF_FREE(local->format); + + CRYPT_STACK_UNWIND(unlink, frame, local->op_ret, local->op_errno, + &local->prebuf, &local->postbuf, xdata); + if (xdata) + dict_unref(xdata); + if (xattr) + dict_unref(xattr); +} + +void +unlink_wind(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + + STACK_WIND(frame, unlink_flush, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, local->loc, local->flags, + local->xdata); +} + +void +rename_unwind(call_frame_t *frame) +{ + crypt_local_t *local = frame->local; + dict_t *xdata; + dict_t *xattr; + struct iatt *prenewparent; + struct iatt *postnewparent; + + if (!local) { + CRYPT_STACK_UNWIND(rename, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL, NULL); + return; + } + xdata = local->xdata; + xattr = local->xattr; + prenewparent = local->prenewparent; + postnewparent = local->postnewparent; + + if (local->loc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + } + if (local->newloc) { + loc_wipe(local->newloc); + GF_FREE(local->newloc); + } + if (local->fd) + fd_unref(local->fd); + if (local->format) + GF_FREE(local->format); + + CRYPT_STACK_UNWIND(rename, frame, local->op_ret, local->op_errno, + &local->buf, &local->prebuf, &local->postbuf, + prenewparent, postnewparent, xdata); + if (xdata) + dict_unref(xdata); + if (xattr) + dict_unref(xattr); + if (prenewparent) + GF_FREE(prenewparent); + if (postnewparent) + GF_FREE(postnewparent); } /* * called as flush_cbk() */ -static int32_t rename_end(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - local->op_ret = op_ret; - local->op_errno = op_errno; - - rename_unwind(frame); - return 0; -} - -static int32_t rename_flush(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, - struct iatt *preoldparent, - struct iatt *postoldparent, - struct iatt *prenewparent, - struct iatt *postnewparent, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto error; - dict_unref(local->xdata); - local->xdata = NULL; - if (xdata) - local->xdata = dict_ref(xdata); - - local->buf = *buf; - local->prebuf = *preoldparent; - local->postbuf = *postoldparent; - if (prenewparent) { - local->prenewparent = GF_CALLOC(1, sizeof(*prenewparent), - gf_crypt_mt_iatt); - if (!local->prenewparent) { - op_errno = ENOMEM; - goto error; - } - *local->prenewparent = *prenewparent; - } - if (postnewparent) { - local->postnewparent = GF_CALLOC(1, sizeof(*postnewparent), - gf_crypt_mt_iatt); - if (!local->postnewparent) { - op_errno = ENOMEM; - goto error; - } - *local->postnewparent = *postnewparent; - } - STACK_WIND(frame, - rename_end, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, - local->fd, - NULL); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - rename_unwind(frame); - return 0; -} - -void rename_wind(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - - STACK_WIND(frame, - rename_flush, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, - local->loc, - local->newloc, - local->xdata); -} - -static int32_t __do_linkop(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - linkop_wind_handler_t wind_fn; - linkop_unwind_handler_t unwind_fn; - - wind_fn = linkop_wind_dispatch(local->fop); - unwind_fn = linkop_unwind_dispatch(local->fop); - - local->op_ret = op_ret; - local->op_errno = op_errno; - - if (op_ret >= 0) - wind_fn(frame, this); - else { - gf_log(this->name, GF_LOG_WARNING, "mtd unlock failed (%d)", - op_errno); - unwind_fn(frame); - } - return 0; -} - -static int32_t do_linkop(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - struct gf_flock lock = {0, }; - crypt_local_t *local = frame->local; - linkop_unwind_handler_t unwind_fn; - - unwind_fn = linkop_unwind_dispatch(local->fop); - local->op_ret = op_ret; - local->op_errno = op_errno; - - if(op_ret < 0) - goto error; - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - - STACK_WIND(frame, - __do_linkop, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - return 0; - error: - unwind_fn(frame); - return 0; +static int32_t +rename_end(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + local->op_ret = op_ret; + local->op_errno = op_errno; + + rename_unwind(frame); + return 0; +} + +static int32_t +rename_flush(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *buf, struct iatt *preoldparent, + struct iatt *postoldparent, struct iatt *prenewparent, + struct iatt *postnewparent, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto error; + dict_unref(local->xdata); + local->xdata = NULL; + if (xdata) + local->xdata = dict_ref(xdata); + + local->buf = *buf; + local->prebuf = *preoldparent; + local->postbuf = *postoldparent; + if (prenewparent) { + local->prenewparent = GF_CALLOC(1, sizeof(*prenewparent), + gf_crypt_mt_iatt); + if (!local->prenewparent) { + op_errno = ENOMEM; + goto error; + } + *local->prenewparent = *prenewparent; + } + if (postnewparent) { + local->postnewparent = GF_CALLOC(1, sizeof(*postnewparent), + gf_crypt_mt_iatt); + if (!local->postnewparent) { + op_errno = ENOMEM; + goto error; + } + *local->postnewparent = *postnewparent; + } + STACK_WIND(frame, rename_end, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, local->fd, NULL); + return 0; +error: + local->op_ret = -1; + local->op_errno = op_errno; + rename_unwind(frame); + return 0; +} + +void +rename_wind(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + + STACK_WIND(frame, rename_flush, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, local->loc, local->newloc, + local->xdata); +} + +static int32_t +__do_linkop(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + linkop_wind_handler_t wind_fn; + linkop_unwind_handler_t unwind_fn; + + wind_fn = linkop_wind_dispatch(local->fop); + unwind_fn = linkop_unwind_dispatch(local->fop); + + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret >= 0) + wind_fn(frame, this); + else { + gf_log(this->name, GF_LOG_WARNING, "mtd unlock failed (%d)", op_errno); + unwind_fn(frame); + } + return 0; +} + +static int32_t +do_linkop(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + struct gf_flock lock = { + 0, + }; + crypt_local_t *local = frame->local; + linkop_unwind_handler_t unwind_fn; + + unwind_fn = linkop_unwind_dispatch(local->fop); + local->op_ret = op_ret; + local->op_errno = op_errno; + + if (op_ret < 0) + goto error; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND(frame, __do_linkop, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + return 0; +error: + unwind_fn(frame); + return 0; } /* * Update the metadata string (against the new pathname); * submit the result */ -static int32_t linkop_begin(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - dict_t *xdata) -{ - gf_boolean_t upload_info; - crypt_local_t *local = frame->local; - crypt_private_t *priv = this->private; - struct crypt_inode_info *info; - data_t *old_mtd; - uint32_t new_mtd_size; - uint64_t value = 0; - void (*unwind_fn)(call_frame_t *frame); - mtd_op_t mop; - - unwind_fn = linkop_unwind_dispatch(local->fop); - mop = linkop_mtdop_dispatch(local->fop); - - if (op_ret < 0) { - /* - * verification failed - */ - goto error; - } else { - fd_bind (fd); +static int32_t +linkop_begin(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + gf_boolean_t upload_info; + crypt_local_t *local = frame->local; + crypt_private_t *priv = this->private; + struct crypt_inode_info *info; + data_t *old_mtd; + uint32_t new_mtd_size; + uint64_t value = 0; + void (*unwind_fn)(call_frame_t * frame); + mtd_op_t mop; + + unwind_fn = linkop_unwind_dispatch(local->fop); + mop = linkop_mtdop_dispatch(local->fop); + + if (op_ret < 0) { + /* + * verification failed + */ + goto error; + } else { + fd_bind(fd); + } + + old_mtd = dict_get(xdata, CRYPTO_FORMAT_PREFIX); + if (!old_mtd) { + op_errno = EIO; + gf_log(this->name, GF_LOG_DEBUG, "Metadata string wasn't found"); + goto error; + } + new_mtd_size = format_size(mop, old_mtd->len); + op_errno = alloc_format(local, new_mtd_size); + if (op_errno) + goto error; + /* + * check for cached info + */ + op_ret = inode_ctx_get(fd->inode, this, &value); + if (op_ret != -1) { + info = (struct crypt_inode_info *)(long)value; + if (info == NULL) { + gf_log(this->name, GF_LOG_WARNING, "Inode info was not found"); + op_errno = EINVAL; + goto error; } - - old_mtd = dict_get(xdata, CRYPTO_FORMAT_PREFIX); - if (!old_mtd) { - op_errno = EIO; - gf_log (this->name, GF_LOG_DEBUG, - "Metadata string wasn't found"); - goto error; - } - new_mtd_size = format_size(mop, old_mtd->len); - op_errno = alloc_format(local, new_mtd_size); - if (op_errno) - goto error; - /* - * check for cached info - */ - op_ret = inode_ctx_get(fd->inode, this, &value); - if (op_ret != -1) { - info = (struct crypt_inode_info *)(long)value; - if (info == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "Inode info was not found"); - op_errno = EINVAL; - goto error; - } - /* - * info was found in the cache - */ - local->info = info; - upload_info = _gf_false; - } - else { - /* - * info wasn't found in the cache; - */ - info = alloc_inode_info(local, local->loc); - if (!info) - goto error; - init_inode_info_head(info, fd); - local->info = info; - upload_info = _gf_true; - } - op_errno = open_format((unsigned char *)old_mtd->data, - old_mtd->len, - local->loc, - info, - get_master_cinfo(priv), - local, - upload_info); - if (op_errno) - goto error; - if (upload_info == _gf_true) { - op_errno = init_inode_info_tail(info, - get_master_cinfo(priv)); - if (op_errno) - goto error; - op_errno = inode_ctx_put(fd->inode, this, - (uint64_t)(long)(info)); - if (op_errno == -1) { - op_errno = EIO; - goto error; - } - } - /* - * update the format string (append/update/cup a MAC) - */ - op_errno = update_format(local->format, - (unsigned char *)old_mtd->data, - old_mtd->len, - local->mac_idx, - mop, - local->newloc, - info, - get_master_cinfo(priv), - local); - if (op_errno) - goto error; - /* - * store the new format string on the server - */ - if (new_mtd_size) { - op_errno = dict_set_static_bin(local->xattr, - CRYPTO_FORMAT_PREFIX, - local->format, - new_mtd_size); - if (op_errno) - goto error; - } - STACK_WIND(frame, - do_linkop, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, - local->loc, - local->xattr, - 0, - NULL); - return 0; - error: - local->op_ret = -1; - local->op_errno = op_errno; - unwind_fn(frame); - return 0; -} - -static int32_t linkop_grab_local(call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc, - int flags, dict_t *xdata, - glusterfs_fop_t op) -{ - int32_t ret = ENOMEM; - fd_t *fd; - crypt_local_t *local; - - local = crypt_alloc_local(frame, this, op); - if (!local) - goto error; - if (xdata) - local->xdata = dict_ref(xdata); - - fd = fd_create(oldloc->inode, frame->root->pid); - if (!fd) { - gf_log(this->name, GF_LOG_ERROR, "Can not create fd"); - goto error; - } - local->fd = fd; - local->flags = flags; - local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!local->loc) - goto error; - ret = loc_copy(local->loc, oldloc); - if (ret) { - GF_FREE(local->loc); - local->loc = NULL; - goto error; - } - if (newloc) { - local->newloc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!local->newloc) { - loc_wipe(local->loc); - GF_FREE(local->loc); - goto error; - } - ret = loc_copy(local->newloc, newloc); - if (ret) { - loc_wipe(local->loc); - GF_FREE(local->loc); - GF_FREE(local->newloc); - goto error; - } - } - local->xattr = dict_new(); - if (!local->xattr) { - gf_log(this->name, GF_LOG_ERROR, "Can not create dict"); - ret = ENOMEM; - goto error; - } - return 0; - + /* + * info was found in the cache + */ + local->info = info; + upload_info = _gf_false; + } else { + /* + * info wasn't found in the cache; + */ + info = alloc_inode_info(local, local->loc); + if (!info) + goto error; + init_inode_info_head(info, fd); + local->info = info; + upload_info = _gf_true; + } + op_errno = open_format((unsigned char *)old_mtd->data, old_mtd->len, + local->loc, info, get_master_cinfo(priv), local, + upload_info); + if (op_errno) + goto error; + if (upload_info == _gf_true) { + op_errno = init_inode_info_tail(info, get_master_cinfo(priv)); + if (op_errno) + goto error; + op_errno = inode_ctx_put(fd->inode, this, (uint64_t)(long)(info)); + if (op_errno == -1) { + op_errno = EIO; + goto error; + } + } + /* + * update the format string (append/update/cup a MAC) + */ + op_errno = update_format(local->format, (unsigned char *)old_mtd->data, + old_mtd->len, local->mac_idx, mop, local->newloc, + info, get_master_cinfo(priv), local); + if (op_errno) + goto error; + /* + * store the new format string on the server + */ + if (new_mtd_size) { + op_errno = dict_set_static_bin(local->xattr, CRYPTO_FORMAT_PREFIX, + local->format, new_mtd_size); + if (op_errno) + goto error; + } + STACK_WIND(frame, do_linkop, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, local->loc, local->xattr, 0, + NULL); + return 0; error: - if (local) { - if (local->xdata) - dict_unref(local->xdata); - if (local->fd) - fd_unref(local->fd); - local->fd = 0; - local->loc = NULL; - local->newloc = NULL; - local->op_ret = -1; - local->op_errno = ret; + local->op_ret = -1; + local->op_errno = op_errno; + unwind_fn(frame); + return 0; +} + +static int32_t +linkop_grab_local(call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, int flags, dict_t *xdata, glusterfs_fop_t op) +{ + int32_t ret = ENOMEM; + fd_t *fd; + crypt_local_t *local; + + local = crypt_alloc_local(frame, this, op); + if (!local) + goto error; + if (xdata) + local->xdata = dict_ref(xdata); + + fd = fd_create(oldloc->inode, frame->root->pid); + if (!fd) { + gf_log(this->name, GF_LOG_ERROR, "Can not create fd"); + goto error; + } + local->fd = fd; + local->flags = flags; + local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!local->loc) + goto error; + ret = loc_copy(local->loc, oldloc); + if (ret) { + GF_FREE(local->loc); + local->loc = NULL; + goto error; + } + if (newloc) { + local->newloc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!local->newloc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + goto error; + } + ret = loc_copy(local->newloc, newloc); + if (ret) { + loc_wipe(local->loc); + GF_FREE(local->loc); + GF_FREE(local->newloc); + goto error; } + } + local->xattr = dict_new(); + if (!local->xattr) { + gf_log(this->name, GF_LOG_ERROR, "Can not create dict"); + ret = ENOMEM; + goto error; + } + return 0; - return ret; +error: + if (local) { + if (local->xdata) + dict_unref(local->xdata); + if (local->fd) + fd_unref(local->fd); + local->fd = 0; + local->loc = NULL; + local->newloc = NULL; + local->op_ret = -1; + local->op_errno = ret; + } + + return ret; } /* @@ -3313,802 +2855,650 @@ error: * submit modified metadata; * wind; */ -static int32_t linkop(call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc, - int flags, - dict_t *xdata, - glusterfs_fop_t op) -{ - int32_t ret; - dict_t *dict; - crypt_local_t *local; - void (*unwind_fn)(call_frame_t *frame); - void (*wind_fn)(call_frame_t *frame, xlator_t *this); - - wind_fn = linkop_wind_dispatch(op); - unwind_fn = linkop_unwind_dispatch(op); - - ret = linkop_grab_local(frame, this, oldloc, newloc, flags, xdata, op); - local = frame->local; - if (ret) - goto error; - - if (local->fd->inode->ia_type == IA_IFLNK) - goto wind; - - dict = dict_new(); - if (!dict) { - gf_log(this->name, GF_LOG_ERROR, "Can not create dict"); - ret = ENOMEM; - goto error; - } - /* - * Set a message to crypt_open() that we need - * locked metadata string. - * All link operations (link, unlink, rename) - * need write lock - */ - msgflags_set_mtd_wlock(&local->msgflags); - ret = dict_set_static_bin(dict, - MSGFLAGS_PREFIX, - &local->msgflags, - sizeof(local->msgflags)); - if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Can not set dict"); - dict_unref(dict); - goto error; - } - /* - * verify metadata against the old pathname - * and retrieve locked metadata string - */ - STACK_WIND(frame, - linkop_begin, - this, - this->fops->open, /* crypt_open() */ - oldloc, - O_RDWR, - local->fd, - dict); - dict_unref(dict); - return 0; +static int32_t +linkop(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + int flags, dict_t *xdata, glusterfs_fop_t op) +{ + int32_t ret; + dict_t *dict; + crypt_local_t *local; + void (*unwind_fn)(call_frame_t * frame); + void (*wind_fn)(call_frame_t * frame, xlator_t * this); + + wind_fn = linkop_wind_dispatch(op); + unwind_fn = linkop_unwind_dispatch(op); + + ret = linkop_grab_local(frame, this, oldloc, newloc, flags, xdata, op); + local = frame->local; + if (ret) + goto error; + + if (local->fd->inode->ia_type == IA_IFLNK) + goto wind; + + dict = dict_new(); + if (!dict) { + gf_log(this->name, GF_LOG_ERROR, "Can not create dict"); + ret = ENOMEM; + goto error; + } + /* + * Set a message to crypt_open() that we need + * locked metadata string. + * All link operations (link, unlink, rename) + * need write lock + */ + msgflags_set_mtd_wlock(&local->msgflags); + ret = dict_set_static_bin(dict, MSGFLAGS_PREFIX, &local->msgflags, + sizeof(local->msgflags)); + if (ret) { + gf_log(this->name, GF_LOG_ERROR, "Can not set dict"); + dict_unref(dict); + goto error; + } + /* + * verify metadata against the old pathname + * and retrieve locked metadata string + */ + STACK_WIND(frame, linkop_begin, this, this->fops->open, /* crypt_open() */ + oldloc, O_RDWR, local->fd, dict); + dict_unref(dict); + return 0; wind: - wind_fn(frame, this); - return 0; + wind_fn(frame, this); + return 0; error: - local->op_ret = -1; - local->op_errno = ret; - unwind_fn(frame); - return 0; -} - -static int32_t crypt_link(call_frame_t *frame, xlator_t *this, - loc_t *oldloc, loc_t *newloc, dict_t *xdata) -{ - return linkop(frame, this, oldloc, newloc, 0, xdata, GF_FOP_LINK); -} - -static int32_t crypt_unlink(call_frame_t *frame, xlator_t *this, - loc_t *loc, int flags, dict_t *xdata) -{ - return linkop(frame, this, loc, NULL, flags, xdata, GF_FOP_UNLINK); -} - -static int32_t crypt_rename(call_frame_t *frame, xlator_t *this, - loc_t *oldloc, loc_t *newloc, dict_t *xdata) -{ - return linkop(frame, this, oldloc, newloc, 0, xdata, GF_FOP_RENAME); -} - -static void put_one_call_open(call_frame_t *frame) -{ - crypt_local_t *local = frame->local; - if (put_one_call(local)) { - fd_t *fd = local->fd; - loc_t *loc = local->loc; - dict_t *xdata = local->xdata; - - CRYPT_STACK_UNWIND(open, - frame, - local->op_ret, - local->op_errno, - fd, - xdata); - fd_unref(fd); - if (xdata) - dict_unref(xdata); - loc_wipe(loc); - GF_FREE(loc); - } -} - -static int32_t __crypt_readv_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - fd_t *local_fd = local->fd; - dict_t *local_xdata = local->xdata; - /* read deals with data configs only */ - struct iovec *avec = local->data_conf.avec; - char **pool = local->data_conf.pool; - int blocks_in_pool = local->data_conf.blocks_in_pool; - struct iobref *iobref = local->iobref; - struct iobref *iobref_data = local->iobref_data; - - if (op_ret < 0) { - gf_log(this->name, GF_LOG_WARNING, - "readv unlock failed (%d)", op_errno); - if (local->op_ret >= 0) { - local->op_ret = op_ret; - local->op_errno = op_errno; - } - } - dump_plain_text(local, avec); - - gf_log("crypt", GF_LOG_DEBUG, - "readv: ret_to_user: %d, iovec len: %d, ia_size: %llu", - (int)(local->rw_count > 0 ? local->rw_count : local->op_ret), - (int)(local->rw_count > 0 ? iov_length(avec, local->data_conf.acount) : 0), - (unsigned long long)local->buf.ia_size); - - CRYPT_STACK_UNWIND(readv, - frame, - local->rw_count > 0 ? local->rw_count : local->op_ret, - local->op_errno, - avec, - avec ? local->data_conf.acount : 0, - &local->buf, - local->iobref, - local_xdata); - - free_avec(avec, pool, blocks_in_pool); - fd_unref(local_fd); - if (local_xdata) - dict_unref(local_xdata); - if (iobref) - iobref_unref(iobref); - if (iobref_data) - iobref_unref(iobref_data); - return 0; -} - -static void crypt_readv_done(call_frame_t *frame, xlator_t *this) -{ - if (parent_is_crypt_xlator(frame, this)) - /* - * don't unlock (it will be done by the parent) - */ - __crypt_readv_done(frame, NULL, this, 0, 0, NULL); - else { - crypt_local_t *local = frame->local; - struct gf_flock lock = {0, }; - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - - STACK_WIND(frame, - __crypt_readv_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - } -} - -static void put_one_call_readv(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - if (put_one_call(local)) - crypt_readv_done(frame, this); -} - -static int32_t __crypt_writev_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - fd_t *local_fd = local->fd; - dict_t *local_xdata = local->xdata; - int32_t ret_to_user; - - if (local->xattr) - dict_unref(local->xattr); - /* - * Calculate amount of butes to be returned - * to user. We need to subtract paddings that - * have been written as a part of atom. - */ - /* - * subtract head padding - */ - if (local->rw_count == 0) - /* - * Nothing has been written, it must be an error - */ - ret_to_user = local->op_ret; - else if (local->rw_count <= local->data_conf.off_in_head) { - gf_log("crypt", GF_LOG_WARNING, "Incomplete write"); - ret_to_user = 0; - } - else - ret_to_user = local->rw_count - - local->data_conf.off_in_head; - /* - * subtract tail padding - */ - if (ret_to_user > local->data_conf.orig_size) - ret_to_user = local->data_conf.orig_size; - - if (local->iobref) - iobref_unref(local->iobref); - if (local->iobref_data) - iobref_unref(local->iobref_data); - free_avec_data(local); - free_avec_hole(local); - - gf_log("crypt", GF_LOG_DEBUG, - "writev: ret_to_user: %d", ret_to_user); - - CRYPT_STACK_UNWIND(writev, - frame, - ret_to_user, - local->op_errno, - &local->prebuf, - &local->postbuf, - local_xdata); - fd_unref(local_fd); - if (local_xdata) - dict_unref(local_xdata); - return 0; -} - -static int32_t crypt_writev_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - gf_log("crypt", GF_LOG_WARNING, "can not update file size"); - - if (parent_is_crypt_xlator(frame, this)) - /* - * don't unlock (it will be done by the parent) - */ - __crypt_writev_done(frame, NULL, this, 0, 0, NULL); - else { - struct gf_flock lock = {0, }; - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - - STACK_WIND(frame, - __crypt_writev_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - } - return 0; -} - -static void put_one_call_writev(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - if (put_one_call(local)) { - if (local->update_disk_file_size) { - int32_t ret; - /* - * update file size, unlock the file and unwind - */ - ret = dict_set(local->xattr, - FSIZE_XATTR_PREFIX, - data_from_uint64(local->cur_file_size)); - if (ret) { - gf_log("crypt", GF_LOG_WARNING, - "can not set key to update file size"); - crypt_writev_done(frame, NULL, - this, 0, 0, NULL); - return; - } - gf_log("crypt", GF_LOG_DEBUG, - "Updating disk file size to %llu", - (unsigned long long)local->cur_file_size); - STACK_WIND(frame, - crypt_writev_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, - local->fd, - local->xattr, /* CRYPTO_FORMAT_PREFIX */ - 0, - NULL); - } - else - crypt_writev_done(frame, NULL, this, 0, 0, NULL); - } -} - -static int32_t __crypt_ftruncate_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - fd_t *local_fd = local->fd; - dict_t *local_xdata = local->xdata; - char *iobase = local->vec.iov_base; - - if (op_ret < 0) { - gf_log(this->name, GF_LOG_WARNING, - "ftruncate unlock failed (%d)", op_errno); - if (local->op_ret >= 0) { - local->op_ret = op_ret; - local->op_errno = op_errno; - } - } - if (local->iobref_data) - iobref_unref(local->iobref_data); - free_avec_data(local); - free_avec_hole(local); - - gf_log("crypt", GF_LOG_DEBUG, - "ftruncate, return to user: presize=%llu, postsize=%llu", - (unsigned long long)local->prebuf.ia_size, - (unsigned long long)local->postbuf.ia_size); - - CRYPT_STACK_UNWIND(ftruncate, - frame, - ((local->op_ret < 0) ? -1 : 0), - local->op_errno, - &local->prebuf, - &local->postbuf, - local_xdata); - fd_unref(local_fd); - if (local_xdata) - dict_unref(local_xdata); - if (iobase) - GF_FREE(iobase); - return 0; -} - -static int32_t crypt_ftruncate_done(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *xdata) -{ - crypt_local_t *local = frame->local; - struct gf_flock lock = {0, }; - - dict_unref(local->xattr); - if (op_ret < 0) - gf_log("crypt", GF_LOG_WARNING, "can not update file size"); - - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - - STACK_WIND(frame, - __crypt_ftruncate_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - this->name, - local->fd, - F_SETLKW, - &lock, - NULL); - return 0; -} - -static void put_one_call_ftruncate(call_frame_t *frame, xlator_t *this) -{ - crypt_local_t *local = frame->local; - if (put_one_call(local)) { - if (local->update_disk_file_size) { - int32_t ret; - /* - * update file size, unlock the file and unwind - */ - ret = dict_set(local->xattr, - FSIZE_XATTR_PREFIX, - data_from_uint64(local->cur_file_size)); - if (ret) { - gf_log("crypt", GF_LOG_WARNING, - "can not set key to update file size"); - crypt_ftruncate_done(frame, NULL, - this, 0, 0, NULL); - return; - } - gf_log("crypt", GF_LOG_DEBUG, - "Updating disk file size to %llu", - (unsigned long long)local->cur_file_size); - STACK_WIND(frame, - crypt_ftruncate_done, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, - local->fd, - local->xattr, /* CRYPTO_FORMAT_PREFIX */ - 0, - NULL); - } - else - crypt_ftruncate_done(frame, NULL, this, 0, 0, NULL); - } + local->op_ret = -1; + local->op_errno = ret; + unwind_fn(frame); + return 0; +} + +static int32_t +crypt_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) +{ + return linkop(frame, this, oldloc, newloc, 0, xdata, GF_FOP_LINK); +} + +static int32_t +crypt_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) +{ + return linkop(frame, this, loc, NULL, flags, xdata, GF_FOP_UNLINK); +} + +static int32_t +crypt_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) +{ + return linkop(frame, this, oldloc, newloc, 0, xdata, GF_FOP_RENAME); +} + +static void +put_one_call_open(call_frame_t *frame) +{ + crypt_local_t *local = frame->local; + if (put_one_call(local)) { + fd_t *fd = local->fd; + loc_t *loc = local->loc; + dict_t *xdata = local->xdata; + + CRYPT_STACK_UNWIND(open, frame, local->op_ret, local->op_errno, fd, + xdata); + fd_unref(fd); + if (xdata) + dict_unref(xdata); + loc_wipe(loc); + GF_FREE(loc); + } +} + +static int32_t +__crypt_readv_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + fd_t *local_fd = local->fd; + dict_t *local_xdata = local->xdata; + /* read deals with data configs only */ + struct iovec *avec = local->data_conf.avec; + char **pool = local->data_conf.pool; + int blocks_in_pool = local->data_conf.blocks_in_pool; + struct iobref *iobref = local->iobref; + struct iobref *iobref_data = local->iobref_data; + + if (op_ret < 0) { + gf_log(this->name, GF_LOG_WARNING, "readv unlock failed (%d)", + op_errno); + if (local->op_ret >= 0) { + local->op_ret = op_ret; + local->op_errno = op_errno; + } + } + dump_plain_text(local, avec); + + gf_log("crypt", GF_LOG_DEBUG, + "readv: ret_to_user: %d, iovec len: %d, ia_size: %llu", + (int)(local->rw_count > 0 ? local->rw_count : local->op_ret), + (int)(local->rw_count > 0 ? iov_length(avec, local->data_conf.acount) + : 0), + (unsigned long long)local->buf.ia_size); + + CRYPT_STACK_UNWIND( + readv, frame, local->rw_count > 0 ? local->rw_count : local->op_ret, + local->op_errno, avec, avec ? local->data_conf.acount : 0, &local->buf, + local->iobref, local_xdata); + + free_avec(avec, pool, blocks_in_pool); + fd_unref(local_fd); + if (local_xdata) + dict_unref(local_xdata); + if (iobref) + iobref_unref(iobref); + if (iobref_data) + iobref_unref(iobref_data); + return 0; +} + +static void +crypt_readv_done(call_frame_t *frame, xlator_t *this) +{ + if (parent_is_crypt_xlator(frame, this)) + /* + * don't unlock (it will be done by the parent) + */ + __crypt_readv_done(frame, NULL, this, 0, 0, NULL); + else { + crypt_local_t *local = frame->local; + struct gf_flock lock = { + 0, + }; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND(frame, __crypt_readv_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + } +} + +static void +put_one_call_readv(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + if (put_one_call(local)) + crypt_readv_done(frame, this); +} + +static int32_t +__crypt_writev_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + fd_t *local_fd = local->fd; + dict_t *local_xdata = local->xdata; + int32_t ret_to_user; + + if (local->xattr) + dict_unref(local->xattr); + /* + * Calculate amount of butes to be returned + * to user. We need to subtract paddings that + * have been written as a part of atom. + */ + /* + * subtract head padding + */ + if (local->rw_count == 0) + /* + * Nothing has been written, it must be an error + */ + ret_to_user = local->op_ret; + else if (local->rw_count <= local->data_conf.off_in_head) { + gf_log("crypt", GF_LOG_WARNING, "Incomplete write"); + ret_to_user = 0; + } else + ret_to_user = local->rw_count - local->data_conf.off_in_head; + /* + * subtract tail padding + */ + if (ret_to_user > local->data_conf.orig_size) + ret_to_user = local->data_conf.orig_size; + + if (local->iobref) + iobref_unref(local->iobref); + if (local->iobref_data) + iobref_unref(local->iobref_data); + free_avec_data(local); + free_avec_hole(local); + + gf_log("crypt", GF_LOG_DEBUG, "writev: ret_to_user: %d", ret_to_user); + + CRYPT_STACK_UNWIND(writev, frame, ret_to_user, local->op_errno, + &local->prebuf, &local->postbuf, local_xdata); + fd_unref(local_fd); + if (local_xdata) + dict_unref(local_xdata); + return 0; +} + +static int32_t +crypt_writev_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + gf_log("crypt", GF_LOG_WARNING, "can not update file size"); + + if (parent_is_crypt_xlator(frame, this)) + /* + * don't unlock (it will be done by the parent) + */ + __crypt_writev_done(frame, NULL, this, 0, 0, NULL); + else { + struct gf_flock lock = { + 0, + }; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND(frame, __crypt_writev_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + } + return 0; +} + +static void +put_one_call_writev(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + if (put_one_call(local)) { + if (local->update_disk_file_size) { + int32_t ret; + /* + * update file size, unlock the file and unwind + */ + ret = dict_set(local->xattr, FSIZE_XATTR_PREFIX, + data_from_uint64(local->cur_file_size)); + if (ret) { + gf_log("crypt", GF_LOG_WARNING, + "can not set key to update file size"); + crypt_writev_done(frame, NULL, this, 0, 0, NULL); + return; + } + gf_log("crypt", GF_LOG_DEBUG, "Updating disk file size to %llu", + (unsigned long long)local->cur_file_size); + STACK_WIND(frame, crypt_writev_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, local->fd, + local->xattr, /* CRYPTO_FORMAT_PREFIX */ + 0, NULL); + } else + crypt_writev_done(frame, NULL, this, 0, 0, NULL); + } +} + +static int32_t +__crypt_ftruncate_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + fd_t *local_fd = local->fd; + dict_t *local_xdata = local->xdata; + char *iobase = local->vec.iov_base; + + if (op_ret < 0) { + gf_log(this->name, GF_LOG_WARNING, "ftruncate unlock failed (%d)", + op_errno); + if (local->op_ret >= 0) { + local->op_ret = op_ret; + local->op_errno = op_errno; + } + } + if (local->iobref_data) + iobref_unref(local->iobref_data); + free_avec_data(local); + free_avec_hole(local); + + gf_log("crypt", GF_LOG_DEBUG, + "ftruncate, return to user: presize=%llu, postsize=%llu", + (unsigned long long)local->prebuf.ia_size, + (unsigned long long)local->postbuf.ia_size); + + CRYPT_STACK_UNWIND(ftruncate, frame, ((local->op_ret < 0) ? -1 : 0), + local->op_errno, &local->prebuf, &local->postbuf, + local_xdata); + fd_unref(local_fd); + if (local_xdata) + dict_unref(local_xdata); + if (iobase) + GF_FREE(iobase); + return 0; +} + +static int32_t +crypt_ftruncate_done(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + crypt_local_t *local = frame->local; + struct gf_flock lock = { + 0, + }; + + dict_unref(local->xattr); + if (op_ret < 0) + gf_log("crypt", GF_LOG_WARNING, "can not update file size"); + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND(frame, __crypt_ftruncate_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, this->name, local->fd, + F_SETLKW, &lock, NULL); + return 0; +} + +static void +put_one_call_ftruncate(call_frame_t *frame, xlator_t *this) +{ + crypt_local_t *local = frame->local; + if (put_one_call(local)) { + if (local->update_disk_file_size) { + int32_t ret; + /* + * update file size, unlock the file and unwind + */ + ret = dict_set(local->xattr, FSIZE_XATTR_PREFIX, + data_from_uint64(local->cur_file_size)); + if (ret) { + gf_log("crypt", GF_LOG_WARNING, + "can not set key to update file size"); + crypt_ftruncate_done(frame, NULL, this, 0, 0, NULL); + return; + } + gf_log("crypt", GF_LOG_DEBUG, "Updating disk file size to %llu", + (unsigned long long)local->cur_file_size); + STACK_WIND(frame, crypt_ftruncate_done, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, local->fd, + local->xattr, /* CRYPTO_FORMAT_PREFIX */ + 0, NULL); + } else + crypt_ftruncate_done(frame, NULL, this, 0, 0, NULL); + } } /* * load regular file size for some FOPs */ -static int32_t load_file_size(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict, - dict_t *xdata) -{ - data_t *data; - crypt_local_t *local = frame->local; - - dict_t *local_xdata = local->xdata; - inode_t *local_inode = local->inode; - - if (op_ret < 0) - goto unwind; - /* - * load regular file size - */ - data = dict_get(dict, FSIZE_XATTR_PREFIX); - if (!data) { - if (local->xdata) - dict_unref(local->xdata); - gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); - op_ret = -1; - op_errno = EIO; - goto unwind; - } - local->buf.ia_size = data_to_uint64(data); - - gf_log(this->name, GF_LOG_DEBUG, - "FOP %d: Translate regular file to %llu", - local->fop, - (unsigned long long)local->buf.ia_size); - unwind: - if (local->fd) - fd_unref(local->fd); - if (local->loc) { - loc_wipe(local->loc); - GF_FREE(local->loc); - } - switch (local->fop) { - case GF_FOP_FSTAT: - CRYPT_STACK_UNWIND(fstat, - frame, - op_ret, - op_errno, - op_ret >= 0 ? &local->buf : NULL, - local->xdata); - break; - case GF_FOP_STAT: - CRYPT_STACK_UNWIND(stat, - frame, - op_ret, - op_errno, - op_ret >= 0 ? &local->buf : NULL, - local->xdata); - break; - case GF_FOP_LOOKUP: - CRYPT_STACK_UNWIND(lookup, - frame, - op_ret, - op_errno, - op_ret >= 0 ? local->inode : NULL, - op_ret >= 0 ? &local->buf : NULL, - local->xdata, - op_ret >= 0 ? &local->postbuf : NULL); - break; - case GF_FOP_READ: - CRYPT_STACK_UNWIND(readv, - frame, - op_ret, - op_errno, - NULL, - 0, - op_ret >= 0 ? &local->buf : NULL, - NULL, - NULL); - break; - default: - gf_log(this->name, GF_LOG_WARNING, - "Improper file operation %d", local->fop); - } - if (local_xdata) - dict_unref(local_xdata); - if (local_inode) - inode_unref(local_inode); - return 0; -} - -static int32_t crypt_stat_common_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf, dict_t *xdata) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto unwind; - if (!IA_ISREG(buf->ia_type)) - goto unwind; - - local->buf = *buf; - if (xdata) - local->xdata = dict_ref(xdata); - - switch (local->fop) { - case GF_FOP_FSTAT: - STACK_WIND(frame, - load_file_size, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - local->fd, - FSIZE_XATTR_PREFIX, - NULL); - break; - case GF_FOP_STAT: - STACK_WIND(frame, - load_file_size, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, - local->loc, - FSIZE_XATTR_PREFIX, - NULL); - break; - default: - gf_log (this->name, GF_LOG_WARNING, - "Improper file operation %d", local->fop); - } - return 0; - unwind: - if (local->fd) - fd_unref(local->fd); - if (local->loc) { - loc_wipe(local->loc); - GF_FREE(local->loc); - } - switch (local->fop) { - case GF_FOP_FSTAT: - CRYPT_STACK_UNWIND(fstat, - frame, - op_ret, - op_errno, - op_ret >= 0 ? buf : NULL, - op_ret >= 0 ? xdata : NULL); - break; - case GF_FOP_STAT: - CRYPT_STACK_UNWIND(stat, - frame, - op_ret, - op_errno, - op_ret >= 0 ? buf : NULL, - op_ret >= 0 ? xdata : NULL); - break; - default: - gf_log (this->name, GF_LOG_WARNING, - "Improper file operation %d", local->fop); - } - return 0; -} - -static int32_t crypt_fstat(call_frame_t *frame, - xlator_t *this, - fd_t *fd, dict_t *xdata) -{ - crypt_local_t *local; - - local = crypt_alloc_local(frame, this, GF_FOP_FSTAT); - if (!local) - goto error; - local->fd = fd_ref(fd); - STACK_WIND(frame, - crypt_stat_common_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, - fd, - xdata); - return 0; - error: - CRYPT_STACK_UNWIND(fstat, - frame, - -1, - ENOMEM, - NULL, - NULL); - return 0; -} - -static int32_t crypt_stat(call_frame_t *frame, - xlator_t *this, - loc_t *loc, dict_t *xdata) -{ - int32_t ret; - crypt_local_t *local; - - local = crypt_alloc_local(frame, this, GF_FOP_STAT); - if (!local) - goto error; - local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!local->loc) - goto error; - ret = loc_copy(local->loc, loc); - if (ret) { - GF_FREE(local->loc); - goto error; - } - STACK_WIND(frame, - crypt_stat_common_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, - loc, - xdata); - return 0; - error: - CRYPT_STACK_UNWIND(stat, - frame, - -1, - ENOMEM, - NULL, - NULL); - return 0; -} - -static int32_t crypt_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 *xdata, - struct iatt *postparent) -{ - crypt_local_t *local = frame->local; - - if (op_ret < 0) - goto unwind; - if (!IA_ISREG(buf->ia_type)) - goto unwind; - - local->inode = inode_ref(inode); - local->buf = *buf; - local->postbuf = *postparent; - if (xdata) - local->xdata = dict_ref(xdata); - gf_uuid_copy(local->loc->gfid, buf->ia_gfid); - - STACK_WIND(frame, - load_file_size, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, - local->loc, - FSIZE_XATTR_PREFIX, - NULL); - return 0; - unwind: - loc_wipe(local->loc); - GF_FREE(local->loc); - CRYPT_STACK_UNWIND(lookup, - frame, - op_ret, - op_errno, - inode, - buf, - xdata, - postparent); - return 0; -} - -static int32_t crypt_lookup(call_frame_t *frame, - xlator_t *this, - loc_t *loc, dict_t *xdata) -{ - int32_t ret; - crypt_local_t *local; - - local = crypt_alloc_local(frame, this, GF_FOP_LOOKUP); - if (!local) - goto error; - local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); - if (!local->loc) - goto error; - ret = loc_copy(local->loc, loc); - if (ret) { - GF_FREE(local->loc); - goto error; - } - gf_log(this->name, GF_LOG_DEBUG, "Lookup %s", loc->path); - STACK_WIND(frame, - crypt_lookup_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, - loc, - xdata); - return 0; - error: - CRYPT_STACK_UNWIND(lookup, - frame, - -1, - ENOMEM, - NULL, - NULL, - NULL, - NULL); - return 0; +static int32_t +load_file_size(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + data_t *data; + crypt_local_t *local = frame->local; + + dict_t *local_xdata = local->xdata; + inode_t *local_inode = local->inode; + + if (op_ret < 0) + goto unwind; + /* + * load regular file size + */ + data = dict_get(dict, FSIZE_XATTR_PREFIX); + if (!data) { + if (local->xdata) + dict_unref(local->xdata); + gf_log("crypt", GF_LOG_WARNING, "Regular file size not found"); + op_ret = -1; + op_errno = EIO; + goto unwind; + } + local->buf.ia_size = data_to_uint64(data); + + gf_log(this->name, GF_LOG_DEBUG, "FOP %d: Translate regular file to %llu", + local->fop, (unsigned long long)local->buf.ia_size); +unwind: + if (local->fd) + fd_unref(local->fd); + if (local->loc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + } + switch (local->fop) { + case GF_FOP_FSTAT: + CRYPT_STACK_UNWIND(fstat, frame, op_ret, op_errno, + op_ret >= 0 ? &local->buf : NULL, local->xdata); + break; + case GF_FOP_STAT: + CRYPT_STACK_UNWIND(stat, frame, op_ret, op_errno, + op_ret >= 0 ? &local->buf : NULL, local->xdata); + break; + case GF_FOP_LOOKUP: + CRYPT_STACK_UNWIND(lookup, frame, op_ret, op_errno, + op_ret >= 0 ? local->inode : NULL, + op_ret >= 0 ? &local->buf : NULL, local->xdata, + op_ret >= 0 ? &local->postbuf : NULL); + break; + case GF_FOP_READ: + CRYPT_STACK_UNWIND(readv, frame, op_ret, op_errno, NULL, 0, + op_ret >= 0 ? &local->buf : NULL, NULL, NULL); + break; + default: + gf_log(this->name, GF_LOG_WARNING, "Improper file operation %d", + local->fop); + } + if (local_xdata) + dict_unref(local_xdata); + if (local_inode) + inode_unref(local_inode); + return 0; +} + +static int32_t +crypt_stat_common_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto unwind; + if (!IA_ISREG(buf->ia_type)) + goto unwind; + + local->buf = *buf; + if (xdata) + local->xdata = dict_ref(xdata); + + switch (local->fop) { + case GF_FOP_FSTAT: + STACK_WIND(frame, load_file_size, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, local->fd, + FSIZE_XATTR_PREFIX, NULL); + break; + case GF_FOP_STAT: + STACK_WIND(frame, load_file_size, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, local->loc, + FSIZE_XATTR_PREFIX, NULL); + break; + default: + gf_log(this->name, GF_LOG_WARNING, "Improper file operation %d", + local->fop); + } + return 0; +unwind: + if (local->fd) + fd_unref(local->fd); + if (local->loc) { + loc_wipe(local->loc); + GF_FREE(local->loc); + } + switch (local->fop) { + case GF_FOP_FSTAT: + CRYPT_STACK_UNWIND(fstat, frame, op_ret, op_errno, + op_ret >= 0 ? buf : NULL, + op_ret >= 0 ? xdata : NULL); + break; + case GF_FOP_STAT: + CRYPT_STACK_UNWIND(stat, frame, op_ret, op_errno, + op_ret >= 0 ? buf : NULL, + op_ret >= 0 ? xdata : NULL); + break; + default: + gf_log(this->name, GF_LOG_WARNING, "Improper file operation %d", + local->fop); + } + return 0; +} + +static int32_t +crypt_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) +{ + crypt_local_t *local; + + local = crypt_alloc_local(frame, this, GF_FOP_FSTAT); + if (!local) + goto error; + local->fd = fd_ref(fd); + STACK_WIND(frame, crypt_stat_common_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); + return 0; +error: + CRYPT_STACK_UNWIND(fstat, frame, -1, ENOMEM, NULL, NULL); + return 0; +} + +static int32_t +crypt_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + int32_t ret; + crypt_local_t *local; + + local = crypt_alloc_local(frame, this, GF_FOP_STAT); + if (!local) + goto error; + local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!local->loc) + goto error; + ret = loc_copy(local->loc, loc); + if (ret) { + GF_FREE(local->loc); + goto error; + } + STACK_WIND(frame, crypt_stat_common_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); + return 0; +error: + CRYPT_STACK_UNWIND(stat, frame, -1, ENOMEM, NULL, NULL); + return 0; +} + +static int32_t +crypt_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 *xdata, struct iatt *postparent) +{ + crypt_local_t *local = frame->local; + + if (op_ret < 0) + goto unwind; + if (!IA_ISREG(buf->ia_type)) + goto unwind; + + local->inode = inode_ref(inode); + local->buf = *buf; + local->postbuf = *postparent; + if (xdata) + local->xdata = dict_ref(xdata); + gf_uuid_copy(local->loc->gfid, buf->ia_gfid); + + STACK_WIND(frame, load_file_size, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, local->loc, + FSIZE_XATTR_PREFIX, NULL); + return 0; +unwind: + loc_wipe(local->loc); + GF_FREE(local->loc); + CRYPT_STACK_UNWIND(lookup, frame, op_ret, op_errno, inode, buf, xdata, + postparent); + return 0; +} + +static int32_t +crypt_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + int32_t ret; + crypt_local_t *local; + + local = crypt_alloc_local(frame, this, GF_FOP_LOOKUP); + if (!local) + goto error; + local->loc = GF_CALLOC(1, sizeof(loc_t), gf_crypt_mt_loc); + if (!local->loc) + goto error; + ret = loc_copy(local->loc, loc); + if (ret) { + GF_FREE(local->loc); + goto error; + } + gf_log(this->name, GF_LOG_DEBUG, "Lookup %s", loc->path); + STACK_WIND(frame, crypt_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + return 0; +error: + CRYPT_STACK_UNWIND(lookup, frame, -1, ENOMEM, NULL, NULL, NULL, NULL); + return 0; } /* * for every regular directory entry find its real file size * and update stat's buf properly */ -static int32_t crypt_readdirp_cbk(call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries, dict_t *xdata) -{ - gf_dirent_t *entry = NULL; - - if (op_ret < 0) - goto unwind; - - list_for_each_entry (entry, (&entries->list), list) { - data_t *data; - - if (!IA_ISREG(entry->d_stat.ia_type)) - continue; - data = dict_get(entry->dict, FSIZE_XATTR_PREFIX); - if (!data){ - gf_log("crypt", GF_LOG_WARNING, - "Regular file size of direntry not found"); - op_errno = EIO; - op_ret = -1; - break; - } - entry->d_stat.ia_size = data_to_uint64(data); - } - unwind: - CRYPT_STACK_UNWIND(readdirp, frame, op_ret, op_errno, entries, xdata); - return 0; +static int32_t +crypt_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + + if (op_ret < 0) + goto unwind; + + list_for_each_entry(entry, (&entries->list), list) + { + data_t *data; + + if (!IA_ISREG(entry->d_stat.ia_type)) + continue; + data = dict_get(entry->dict, FSIZE_XATTR_PREFIX); + if (!data) { + gf_log("crypt", GF_LOG_WARNING, + "Regular file size of direntry not found"); + op_errno = EIO; + op_ret = -1; + break; + } + entry->d_stat.ia_size = data_to_uint64(data); + } +unwind: + CRYPT_STACK_UNWIND(readdirp, frame, op_ret, op_errno, entries, xdata); + return 0; } /* @@ -4116,401 +3506,392 @@ static int32_t crypt_readdirp_cbk(call_frame_t *frame, * file sizes for all directory entries of the parent @fd. * Actual updates take place in ->crypt_readdirp_cbk() */ -static int32_t crypt_readdirp(call_frame_t *frame, xlator_t *this, - fd_t *fd, size_t size, off_t offset, - dict_t *xdata) -{ - int32_t ret = ENOMEM; - - if (!xdata) { - xdata = dict_new(); - if (!xdata) - goto error; - } - else - dict_ref(xdata); - /* - * make sure that we'll have real file sizes at ->readdirp_cbk() - */ - ret = dict_set(xdata, FSIZE_XATTR_PREFIX, data_from_uint64(0)); - if (ret) { - dict_unref(xdata); - ret = ENOMEM; - goto error; - } - STACK_WIND(frame, - crypt_readdirp_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdirp, - fd, - size, - offset, - xdata); - dict_unref(xdata); - return 0; - error: - CRYPT_STACK_UNWIND(readdirp, frame, -1, ret, NULL, NULL); - return 0; -} - -static int32_t crypt_access(call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask, dict_t *xdata) -{ - gf_log(this->name, GF_LOG_WARNING, - "NFS mounts of encrypted volumes are unsupported"); - CRYPT_STACK_UNWIND(access, frame, -1, EPERM, NULL); - return 0; -} - -int32_t master_set_block_size (xlator_t *this, crypt_private_t *priv, - dict_t *options) -{ - uint64_t block_size = 0; - struct master_cipher_info *master = get_master_cinfo(priv); - - if (options != NULL) - GF_OPTION_RECONF("block-size", block_size, options, - size_uint64, error); - else - GF_OPTION_INIT("block-size", block_size, size_uint64, error); - - switch (block_size) { - case 512: - master->m_block_bits = 9; - break; - case 1024: - master->m_block_bits = 10; - break; - case 2048: - master->m_block_bits = 11; - break; - case 4096: - master->m_block_bits = 12; - break; - default: - gf_log("crypt", GF_LOG_ERROR, - "FATAL: unsupported block size %llu", - (unsigned long long)block_size); - goto error; - } - return 0; - error: - return -1; -} - -int32_t master_set_alg(xlator_t *this, crypt_private_t *priv) -{ - struct master_cipher_info *master = get_master_cinfo(priv); - master->m_alg = AES_CIPHER_ALG; - return 0; -} - -int32_t master_set_mode(xlator_t *this, crypt_private_t *priv) -{ - struct master_cipher_info *master = get_master_cinfo(priv); - master->m_mode = XTS_CIPHER_MODE; - return 0; +static int32_t +crypt_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, dict_t *xdata) +{ + int32_t ret = ENOMEM; + + if (!xdata) { + xdata = dict_new(); + if (!xdata) + goto error; + } else + dict_ref(xdata); + /* + * make sure that we'll have real file sizes at ->readdirp_cbk() + */ + ret = dict_set(xdata, FSIZE_XATTR_PREFIX, data_from_uint64(0)); + if (ret) { + dict_unref(xdata); + ret = ENOMEM; + goto error; + } + STACK_WIND(frame, crypt_readdirp_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, fd, size, offset, xdata); + dict_unref(xdata); + return 0; +error: + CRYPT_STACK_UNWIND(readdirp, frame, -1, ret, NULL, NULL); + return 0; +} + +static int32_t +crypt_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, + dict_t *xdata) +{ + gf_log(this->name, GF_LOG_WARNING, + "NFS mounts of encrypted volumes are unsupported"); + CRYPT_STACK_UNWIND(access, frame, -1, EPERM, NULL); + return 0; +} + +int32_t +master_set_block_size(xlator_t *this, crypt_private_t *priv, dict_t *options) +{ + uint64_t block_size = 0; + struct master_cipher_info *master = get_master_cinfo(priv); + + if (options != NULL) + GF_OPTION_RECONF("block-size", block_size, options, size_uint64, error); + else + GF_OPTION_INIT("block-size", block_size, size_uint64, error); + + switch (block_size) { + case 512: + master->m_block_bits = 9; + break; + case 1024: + master->m_block_bits = 10; + break; + case 2048: + master->m_block_bits = 11; + break; + case 4096: + master->m_block_bits = 12; + break; + default: + gf_log("crypt", GF_LOG_ERROR, "FATAL: unsupported block size %llu", + (unsigned long long)block_size); + goto error; + } + return 0; +error: + return -1; +} + +int32_t +master_set_alg(xlator_t *this, crypt_private_t *priv) +{ + struct master_cipher_info *master = get_master_cinfo(priv); + master->m_alg = AES_CIPHER_ALG; + return 0; +} + +int32_t +master_set_mode(xlator_t *this, crypt_private_t *priv) +{ + struct master_cipher_info *master = get_master_cinfo(priv); + master->m_mode = XTS_CIPHER_MODE; + return 0; } /* * set key size in bits to the master info * Pre-conditions: cipher mode in the master info is uptodate. */ -static int master_set_data_key_size (xlator_t *this, crypt_private_t *priv, - dict_t *options) -{ - int32_t ret; - uint64_t key_size = 0; - struct master_cipher_info *master = get_master_cinfo(priv); - - if (options != NULL) - GF_OPTION_RECONF("data-key-size", key_size, options, - uint64, error); - else - GF_OPTION_INIT("data-key-size", key_size, uint64, error); - - ret = data_cipher_algs[master->m_alg][master->m_mode].check_key(key_size); - if (ret) { - gf_log("crypt", GF_LOG_ERROR, - "FATAL: wrong bin key size %llu for alg %d mode %d", - (unsigned long long)key_size, - (int)master->m_alg, - (int)master->m_mode); - goto error; - } - master->m_dkey_size = key_size; - return 0; - error: - return -1; -} - -static int is_hex(char *s) { - return ('0' <= *s && *s <= '9') || ('a' <= *s && *s <= 'f'); -} - -static int parse_hex_buf(xlator_t *this, char *src, unsigned char *dst, - int hex_size) -{ - int i; - int hex_byte = 0; - - for (i = 0; i < (hex_size / 2); i++) { - if (!is_hex(src + i*2) || !is_hex(src + i*2 + 1)) { - gf_log("crypt", GF_LOG_ERROR, - "FATAL: not hex symbol in key"); - return -1; - } - if (sscanf(src + i*2, "%2x", &hex_byte) != 1) { - gf_log("crypt", GF_LOG_ERROR, - "FATAL: can not parse hex key"); - return -1; - } - dst[i] = hex_byte & 0xff; - } - return 0; +static int +master_set_data_key_size(xlator_t *this, crypt_private_t *priv, dict_t *options) +{ + int32_t ret; + uint64_t key_size = 0; + struct master_cipher_info *master = get_master_cinfo(priv); + + if (options != NULL) + GF_OPTION_RECONF("data-key-size", key_size, options, uint64, error); + else + GF_OPTION_INIT("data-key-size", key_size, uint64, error); + + ret = data_cipher_algs[master->m_alg][master->m_mode].check_key(key_size); + if (ret) { + gf_log("crypt", GF_LOG_ERROR, + "FATAL: wrong bin key size %llu for alg %d mode %d", + (unsigned long long)key_size, (int)master->m_alg, + (int)master->m_mode); + goto error; + } + master->m_dkey_size = key_size; + return 0; +error: + return -1; +} + +static int +is_hex(char *s) +{ + return ('0' <= *s && *s <= '9') || ('a' <= *s && *s <= 'f'); +} + +static int +parse_hex_buf(xlator_t *this, char *src, unsigned char *dst, int hex_size) +{ + int i; + int hex_byte = 0; + + for (i = 0; i < (hex_size / 2); i++) { + if (!is_hex(src + i * 2) || !is_hex(src + i * 2 + 1)) { + gf_log("crypt", GF_LOG_ERROR, "FATAL: not hex symbol in key"); + return -1; + } + if (sscanf(src + i * 2, "%2x", &hex_byte) != 1) { + gf_log("crypt", GF_LOG_ERROR, "FATAL: can not parse hex key"); + return -1; + } + dst[i] = hex_byte & 0xff; + } + return 0; } /* * Parse options; * install master volume key */ -int32_t master_set_master_vol_key(xlator_t *this, crypt_private_t *priv) -{ - int32_t ret; - FILE *file = NULL; - - int32_t key_size; - char *opt_key_file_pathname = NULL; - - unsigned char bin_buf[MASTER_VOL_KEY_SIZE]; - char hex_buf[2 * MASTER_VOL_KEY_SIZE]; - - struct master_cipher_info *master = get_master_cinfo(priv); - /* - * extract master key passed via option - */ - GF_OPTION_INIT("master-key", opt_key_file_pathname, path, bad_key); - - if (!opt_key_file_pathname) { - gf_log(this->name, GF_LOG_ERROR, "FATAL: missing master key"); - return -1; - } - gf_log(this->name, GF_LOG_DEBUG, "handling file key %s", - opt_key_file_pathname); - - file = fopen(opt_key_file_pathname, "r"); - if (file == NULL) { - gf_log(this->name, GF_LOG_ERROR, - "FATAL: can not open file with master key"); - return -1; - } - /* - * extract hex key - */ - key_size = fread(hex_buf, 1, sizeof(hex_buf), file); - if (key_size < sizeof(hex_buf)) { - gf_log(this->name, GF_LOG_ERROR, - "FATAL: master key is too short"); - goto bad_key; - } - ret = parse_hex_buf(this, hex_buf, bin_buf, key_size); - if (ret) - goto bad_key; - memcpy(master->m_key, bin_buf, MASTER_VOL_KEY_SIZE); - memset(hex_buf, 0, sizeof(hex_buf)); - fclose(file); - - memset(bin_buf, 0, sizeof(bin_buf)); - return 0; - bad_key: - gf_log(this->name, GF_LOG_ERROR, "FATAL: bad master key"); - if (file) - fclose(file); - memset(bin_buf, 0, sizeof(bin_buf)); - return -1; +int32_t +master_set_master_vol_key(xlator_t *this, crypt_private_t *priv) +{ + int32_t ret; + FILE *file = NULL; + + int32_t key_size; + char *opt_key_file_pathname = NULL; + + unsigned char bin_buf[MASTER_VOL_KEY_SIZE]; + char hex_buf[2 * MASTER_VOL_KEY_SIZE]; + + struct master_cipher_info *master = get_master_cinfo(priv); + /* + * extract master key passed via option + */ + GF_OPTION_INIT("master-key", opt_key_file_pathname, path, bad_key); + + if (!opt_key_file_pathname) { + gf_log(this->name, GF_LOG_ERROR, "FATAL: missing master key"); + return -1; + } + gf_log(this->name, GF_LOG_DEBUG, "handling file key %s", + opt_key_file_pathname); + + file = fopen(opt_key_file_pathname, "r"); + if (file == NULL) { + gf_log(this->name, GF_LOG_ERROR, + "FATAL: can not open file with master key"); + return -1; + } + /* + * extract hex key + */ + key_size = fread(hex_buf, 1, sizeof(hex_buf), file); + if (key_size < sizeof(hex_buf)) { + gf_log(this->name, GF_LOG_ERROR, "FATAL: master key is too short"); + goto bad_key; + } + ret = parse_hex_buf(this, hex_buf, bin_buf, key_size); + if (ret) + goto bad_key; + memcpy(master->m_key, bin_buf, MASTER_VOL_KEY_SIZE); + memset(hex_buf, 0, sizeof(hex_buf)); + fclose(file); + + memset(bin_buf, 0, sizeof(bin_buf)); + return 0; +bad_key: + gf_log(this->name, GF_LOG_ERROR, "FATAL: bad master key"); + if (file) + fclose(file); + memset(bin_buf, 0, sizeof(bin_buf)); + return -1; } /* * Derive volume key for object-id authentication */ -int32_t master_set_nmtd_vol_key(xlator_t *this, crypt_private_t *priv) +int32_t +master_set_nmtd_vol_key(xlator_t *this, crypt_private_t *priv) { - return get_nmtd_vol_key(get_master_cinfo(priv)); + return get_nmtd_vol_key(get_master_cinfo(priv)); } -int32_t crypt_init_xlator(xlator_t *this) +int32_t +crypt_init_xlator(xlator_t *this) { - int32_t ret; - crypt_private_t *priv = this->private; + int32_t ret; + crypt_private_t *priv = this->private; - ret = master_set_alg(this, priv); - if (ret) - return ret; - ret = master_set_mode(this, priv); - if (ret) - return ret; - ret = master_set_block_size(this, priv, NULL); - if (ret) - return ret; - ret = master_set_data_key_size(this, priv, NULL); - if (ret) - return ret; - ret = master_set_master_vol_key(this, priv); - if (ret) - return ret; - return master_set_nmtd_vol_key(this, priv); + ret = master_set_alg(this, priv); + if (ret) + return ret; + ret = master_set_mode(this, priv); + if (ret) + return ret; + ret = master_set_block_size(this, priv, NULL); + if (ret) + return ret; + ret = master_set_data_key_size(this, priv, NULL); + if (ret) + return ret; + ret = master_set_master_vol_key(this, priv); + if (ret) + return ret; + return master_set_nmtd_vol_key(this, priv); } -static int32_t crypt_alloc_private(xlator_t *this) +static int32_t +crypt_alloc_private(xlator_t *this) { - this->private = GF_CALLOC(1, sizeof(crypt_private_t), gf_crypt_mt_priv); - if (!this->private) { - gf_log("crypt", GF_LOG_ERROR, - "Can not allocate memory for private data"); - return ENOMEM; - } - return 0; + this->private = GF_CALLOC(1, sizeof(crypt_private_t), gf_crypt_mt_priv); + if (!this->private) { + gf_log("crypt", GF_LOG_ERROR, + "Can not allocate memory for private data"); + return ENOMEM; + } + return 0; } -static void crypt_free_private(xlator_t *this) +static void +crypt_free_private(xlator_t *this) { - crypt_private_t *priv = this->private; - if (priv) { - memset(priv, 0, sizeof(*priv)); - GF_FREE(priv); - } + crypt_private_t *priv = this->private; + if (priv) { + memset(priv, 0, sizeof(*priv)); + GF_FREE(priv); + } } int32_t -mem_acct_init (xlator_t *this) +mem_acct_init(xlator_t *this) { - int ret = -1; + int ret = -1; + + if (!this) + return ret; - if (!this) - return ret; + ret = xlator_mem_acct_init(this, gf_crypt_mt_end); - ret = xlator_mem_acct_init (this, gf_crypt_mt_end); + if (ret != 0) { + gf_log(this->name, GF_LOG_ERROR, + "Memory accounting init" + "failed"); + return ret; + } - if (ret != 0) { - gf_log(this->name, GF_LOG_ERROR, "Memory accounting init" - "failed"); - return ret; - } + return ret; +} + +int32_t +reconfigure(xlator_t *this, dict_t *options) +{ + int32_t ret = -1; + crypt_private_t *priv = NULL; + + GF_VALIDATE_OR_GOTO("crypt", this, error); + GF_VALIDATE_OR_GOTO(this->name, this->private, error); + GF_VALIDATE_OR_GOTO(this->name, options, error); + + priv = this->private; + + ret = master_set_block_size(this, priv, options); + if (ret) { + gf_log("this->name", GF_LOG_ERROR, "Failed to reconfure block size"); + goto error; + } + ret = master_set_data_key_size(this, priv, options); + if (ret) { + gf_log("this->name", GF_LOG_ERROR, "Failed to reconfure data key size"); + goto error; + } + return 0; +error: + return ret; +} +int32_t +init(xlator_t *this) +{ + int32_t ret; + + if (!this->children || this->children->next) { + gf_log("crypt", GF_LOG_ERROR, + "FATAL: crypt should have exactly one child"); + return EINVAL; + } + if (!this->parents) { + gf_log(this->name, GF_LOG_WARNING, "dangling volume. check volfile "); + } + ret = crypt_alloc_private(this); + if (ret) return ret; + ret = crypt_init_xlator(this); + if (ret) + goto error; + this->local_pool = mem_pool_new(crypt_local_t, 64); + if (!this->local_pool) { + gf_log(this->name, GF_LOG_ERROR, + "failed to create local_t's memory pool"); + ret = ENOMEM; + goto error; + } + gf_log("crypt", GF_LOG_INFO, "crypt xlator loaded"); + return 0; +error: + crypt_free_private(this); + return ret; } -int32_t reconfigure (xlator_t *this, dict_t *options) -{ - int32_t ret = -1; - crypt_private_t *priv = NULL; - - GF_VALIDATE_OR_GOTO ("crypt", this, error); - GF_VALIDATE_OR_GOTO (this->name, this->private, error); - GF_VALIDATE_OR_GOTO (this->name, options, error); - - priv = this->private; - - ret = master_set_block_size(this, priv, options); - if (ret) { - gf_log("this->name", GF_LOG_ERROR, - "Failed to reconfure block size"); - goto error; - } - ret = master_set_data_key_size(this, priv, options); - if (ret) { - gf_log("this->name", GF_LOG_ERROR, - "Failed to reconfure data key size"); - goto error; - } - return 0; - error: - return ret; -} - -int32_t init(xlator_t *this) -{ - int32_t ret; - - if (!this->children || this->children->next) { - gf_log ("crypt", GF_LOG_ERROR, - "FATAL: crypt should have exactly one child"); - return EINVAL; - } - if (!this->parents) { - gf_log (this->name, GF_LOG_WARNING, - "dangling volume. check volfile "); - } - ret = crypt_alloc_private(this); - if (ret) - return ret; - ret = crypt_init_xlator(this); - if (ret) - goto error; - this->local_pool = mem_pool_new(crypt_local_t, 64); - if (!this->local_pool) { - gf_log(this->name, GF_LOG_ERROR, - "failed to create local_t's memory pool"); - ret = ENOMEM; - goto error; - } - gf_log ("crypt", GF_LOG_INFO, "crypt xlator loaded"); - return 0; - error: - crypt_free_private(this); - return ret; -} - -void fini (xlator_t *this) -{ - crypt_free_private(this); -} - -struct xlator_fops fops = { - .readv = crypt_readv, - .writev = crypt_writev, - .truncate = crypt_truncate, - .ftruncate = crypt_ftruncate, - .setxattr = crypt_setxattr, - .fsetxattr = crypt_fsetxattr, - .link = crypt_link, - .unlink = crypt_unlink, - .rename = crypt_rename, - .open = crypt_open, - .create = crypt_create, - .stat = crypt_stat, - .fstat = crypt_fstat, - .lookup = crypt_lookup, - .readdirp = crypt_readdirp, - .access = crypt_access -}; +void +fini(xlator_t *this) +{ + crypt_free_private(this); +} -struct xlator_cbks cbks = { - .forget = crypt_forget -}; +struct xlator_fops fops = {.readv = crypt_readv, + .writev = crypt_writev, + .truncate = crypt_truncate, + .ftruncate = crypt_ftruncate, + .setxattr = crypt_setxattr, + .fsetxattr = crypt_fsetxattr, + .link = crypt_link, + .unlink = crypt_unlink, + .rename = crypt_rename, + .open = crypt_open, + .create = crypt_create, + .stat = crypt_stat, + .fstat = crypt_fstat, + .lookup = crypt_lookup, + .readdirp = crypt_readdirp, + .access = crypt_access}; + +struct xlator_cbks cbks = {.forget = crypt_forget}; struct volume_options options[] = { - { .key = {"master-key"}, - .type = GF_OPTION_TYPE_PATH, - .description = "Pathname of regular file which contains master volume key" - }, - { .key = {"data-key-size"}, - .type = GF_OPTION_TYPE_SIZET, - .description = "Data key size (bits)", - .min = 256, - .max = 512, - .default_value = "256", - }, - { .key = {"block-size"}, - .type = GF_OPTION_TYPE_SIZET, - .description = "Atom size (bits)", - .min = 512, - .max = 4096, - .default_value = "4096" - }, - { .key = {NULL} }, + {.key = {"master-key"}, + .type = GF_OPTION_TYPE_PATH, + .description = + "Pathname of regular file which contains master volume key"}, + { + .key = {"data-key-size"}, + .type = GF_OPTION_TYPE_SIZET, + .description = "Data key size (bits)", + .min = 256, + .max = 512, + .default_value = "256", + }, + {.key = {"block-size"}, + .type = GF_OPTION_TYPE_SIZET, + .description = "Atom size (bits)", + .min = 512, + .max = 4096, + .default_value = "4096"}, + {.key = {NULL}}, }; /* |