[Devel] [PATCH 1/2] fs/fuse kio_pcs: handle error of submit_size_grow()
Before continuing write requests, we need to check the procedure size grow was successful. If the size attribute of a file failed to increase, it makes no sense to continue to push write requests because they will not be able to succeed until the file size will match. Signed-off-by: Pavel Butsykin --- fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 14 +- fs/fuse/kio/pcs/pcs_map.c | 34 -- fs/fuse/kio/pcs/pcs_req.c | 31 +++ fs/fuse/kio/pcs/pcs_req.h | 2 ++ 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c index cf97a5ce0e50..1a6776f7977a 100644 --- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c +++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c @@ -654,6 +654,7 @@ static void fuse_size_grow_work(struct work_struct *w) struct inode *inode = >inode->inode; struct pcs_int_request* ireq, *next; unsigned long long size = 0; + int err; LIST_HEAD(to_submit); spin_lock(>lock); @@ -673,7 +674,18 @@ static void fuse_size_grow_work(struct work_struct *w) } di->size.required = size; spin_unlock(>lock); - submit_size_grow(inode, size); + + err = submit_size_grow(inode, size); + if (err) { + LIST_HEAD(to_fail); + + spin_lock(>lock); + list_splice_tail_init(>size.grow_queue, _fail); + spin_unlock(>lock); + + pcs_ireq_queue_fail(_fail, err); + return; + } spin_lock(>lock); BUG_ON(di->size.shrink); diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c index 90e311f7e995..78e773536bb4 100644 --- a/fs/fuse/kio/pcs/pcs_map.c +++ b/fs/fuse/kio/pcs/pcs_map.c @@ -26,8 +26,6 @@ */ #define MAP_BATCH 16 -static void pcs_ireq_queue_fail(struct list_head *queue, int error); - abs_time_t get_real_time_ms(void) { struct timespec tv = current_kernel_time(); @@ -138,7 +136,6 @@ static void pcs_map_reset(struct pcs_map_entry * m) { m->state &= ~(PCS_MAP_READABLE|PCS_MAP_WRITEABLE); } -static void pcs_ireq_queue_fail(struct list_head *queue, int error); static void map_sync_work_add(struct pcs_map_entry *m, unsigned long timeout); static void map_sync_work_del(struct pcs_map_entry *m); @@ -724,37 +721,6 @@ void pcs_map_notify_addr_change(struct pcs_cs * cs) } } -noinline static void pcs_ireq_queue_fail(struct list_head *queue, int error) -{ - while (!list_empty(queue)) { - struct pcs_int_request *ireq = list_first_entry(queue, struct pcs_int_request, list); - - list_del_init(>list); - - pcs_set_local_error(>error, error); - - if (ireq->type == PCS_IREQ_TRUNCATE) { - ireq_on_error(ireq); - - if (!(ireq->flags & IREQ_F_FATAL)) { - if (ireq_is_timed_out(ireq)) { - pcs_log(LOG_ERR, "timeout while truncate(%d) request on \"" DENTRY_FMT "\" last err=%u", - ireq->type, DENTRY_ARGS(ireq->dentry), ireq->error.value); - BUG(); - } - pcs_clear_error(>error); - - TRACE("requeue truncate(%d) %llu@" DENTRY_FMT "\n", ireq->type, - (unsigned long long)ireq->truncreq.offset, DENTRY_ARGS(ireq->dentry)); - - ireq_delay(ireq); - continue; - } - } - ireq_complete(ireq); - } -} - void transfer_sync_data(struct pcs_cs_list * new_cs_list, struct pcs_cs_list * old_cs_list) { int i, k; diff --git a/fs/fuse/kio/pcs/pcs_req.c b/fs/fuse/kio/pcs/pcs_req.c index a05f1e43c94c..9516768c47d4 100644 --- a/fs/fuse/kio/pcs/pcs_req.c +++ b/fs/fuse/kio/pcs/pcs_req.c @@ -121,3 +121,34 @@ void ireq_handle_hole(struct pcs_int_request *ireq) ireq_complete(ireq); } + +noinline void pcs_ireq_queue_fail(struct list_head *queue, int error) +{ + while (!list_empty(queue)) { + struct pcs_int_request *ireq = list_first_entry(queue, struct pcs_int_request, list); + + list_del_init(>list); + + pcs_set_local_error(>error, error); + + if (ireq->type == PCS_IREQ_TRUNCATE) { + ireq_on_error(ireq); + + if (!(ireq->flags & IREQ_F_FATAL)) { + if (ireq_is_timed_out(ireq)) { + pcs_log(LOG_ERR, "timeout while truncate(%d) request on \"" DENTRY_FMT "\" last err=%u", + ireq->type, DENTRY_ARGS(ireq->dentry), ireq->error.value); +
[Devel] [PATCH 0/2] fuse_kdirect: fsync hungs after unlink fixes
#VSTOR-10635 Pavel Butsykin (2): fs/fuse kio_pcs: handle error of submit_size_grow() fs/fuse kio_pcs: pass the file handle for FUSE_SETATTR request fs/fuse/file.c | 5 +++-- fs/fuse/fuse_i.h | 4 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 22 +- fs/fuse/kio/pcs/pcs_map.c | 34 -- fs/fuse/kio/pcs/pcs_req.c | 31 +++ fs/fuse/kio/pcs/pcs_req.h | 2 ++ 6 files changed, 61 insertions(+), 37 deletions(-) -- 2.15.1 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH 2/2] fs/fuse kio_pcs: pass the file handle for FUSE_SETATTR request
Add to pass the file handle (if it is) for FUSE_SETATTR request inside submit_size_grow(). Signed-off-by: Pavel Butsykin --- fs/fuse/file.c | 5 +++-- fs/fuse/fuse_i.h | 4 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 8 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ddfb41af54ec..9ae260a10490 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1137,6 +1137,7 @@ void fuse_release_ff(struct inode *inode, struct fuse_file *ff) } } } +EXPORT_SYMBOL_GPL(fuse_release_ff); static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) { @@ -1997,8 +1998,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) fuse_writepage_free(fc, req); } -static struct fuse_file *fuse_write_file(struct fuse_conn *fc, -struct fuse_inode *fi) +struct fuse_file *fuse_write_file(struct fuse_conn *fc, struct fuse_inode *fi) { struct fuse_file *ff = NULL; @@ -2011,6 +2011,7 @@ static struct fuse_file *fuse_write_file(struct fuse_conn *fc, return ff; } +EXPORT_SYMBOL_GPL(fuse_write_file); static int tree_insert(struct rb_root *root, struct fuse_req *ins_req) { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 939835f585b1..20295250070a 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1091,4 +1091,8 @@ void fuse_stat_account(struct fuse_conn * fc, int op, ktime_t val); int fuse_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len); +struct fuse_file *fuse_write_file(struct fuse_conn *fc, struct fuse_inode *fi); + +void fuse_release_ff(struct inode *inode, struct fuse_file *ff); + #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c index 1a6776f7977a..4f8b0133ca5b 100644 --- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c +++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c @@ -608,6 +608,7 @@ void ireq_destroy(struct pcs_int_request *ireq) static int submit_size_grow(struct inode *inode, unsigned long long size) { struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_file *ff; struct fuse_setattr_in inarg; struct fuse_attr_out outarg; struct fuse_req *req; @@ -630,6 +631,11 @@ static int submit_size_grow(struct inode *inode, unsigned long long size) inarg.valid |= FATTR_SIZE; inarg.size = size; + ff = fuse_write_file(fc, get_fuse_inode(inode)); + if (ff) { + inarg.valid |= FATTR_FH; + inarg.fh = ff->fh; + } req->io_inode = inode; req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); @@ -641,7 +647,9 @@ static int submit_size_grow(struct inode *inode, unsigned long long size) req->out.args[0].value = fuse_request_send(fc, req); + err = req->out.h.error; + fuse_release_ff(inode, ff); fuse_put_request(fc, req); return err; -- 2.15.1 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
Re: [Devel] [PATCH 1/2] fs/fuse kio_pcs: handle error of submit_size_grow()
On 07.06.2018 17:40, Pavel Butsykin wrote: Before continuing write requests, we need to check the procedure size grow was successful. If the size attribute of a file failed to increase, it makes no sense to continue to push write requests because they will not be able to succeed until the file size will match. Alexey, I wonder whether we should abort pending requests for all errors or just for fatal? for which errors we can retry FUSE_SETATTR request? Signed-off-by: Pavel Butsykin --- fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 14 +- fs/fuse/kio/pcs/pcs_map.c | 34 -- fs/fuse/kio/pcs/pcs_req.c | 31 +++ fs/fuse/kio/pcs/pcs_req.h | 2 ++ 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c index cf97a5ce0e50..1a6776f7977a 100644 --- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c +++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c @@ -654,6 +654,7 @@ static void fuse_size_grow_work(struct work_struct *w) struct inode *inode = >inode->inode; struct pcs_int_request* ireq, *next; unsigned long long size = 0; + int err; LIST_HEAD(to_submit); spin_lock(>lock); @@ -673,7 +674,18 @@ static void fuse_size_grow_work(struct work_struct *w) } di->size.required = size; spin_unlock(>lock); - submit_size_grow(inode, size); + + err = submit_size_grow(inode, size); + if (err) { + LIST_HEAD(to_fail); + + spin_lock(>lock); + list_splice_tail_init(>size.grow_queue, _fail); + spin_unlock(>lock); + + pcs_ireq_queue_fail(_fail, err); + return; + } spin_lock(>lock); BUG_ON(di->size.shrink); diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c index 90e311f7e995..78e773536bb4 100644 --- a/fs/fuse/kio/pcs/pcs_map.c +++ b/fs/fuse/kio/pcs/pcs_map.c @@ -26,8 +26,6 @@ */ #define MAP_BATCH 16 -static void pcs_ireq_queue_fail(struct list_head *queue, int error); - abs_time_t get_real_time_ms(void) { struct timespec tv = current_kernel_time(); @@ -138,7 +136,6 @@ static void pcs_map_reset(struct pcs_map_entry * m) { m->state &= ~(PCS_MAP_READABLE|PCS_MAP_WRITEABLE); } -static void pcs_ireq_queue_fail(struct list_head *queue, int error); static void map_sync_work_add(struct pcs_map_entry *m, unsigned long timeout); static void map_sync_work_del(struct pcs_map_entry *m); @@ -724,37 +721,6 @@ void pcs_map_notify_addr_change(struct pcs_cs * cs) } } -noinline static void pcs_ireq_queue_fail(struct list_head *queue, int error) -{ - while (!list_empty(queue)) { - struct pcs_int_request *ireq = list_first_entry(queue, struct pcs_int_request, list); - - list_del_init(>list); - - pcs_set_local_error(>error, error); - - if (ireq->type == PCS_IREQ_TRUNCATE) { - ireq_on_error(ireq); - - if (!(ireq->flags & IREQ_F_FATAL)) { - if (ireq_is_timed_out(ireq)) { - pcs_log(LOG_ERR, "timeout while truncate(%d) request on \"" DENTRY_FMT "\" last err=%u", - ireq->type, DENTRY_ARGS(ireq->dentry), ireq->error.value); - BUG(); - } - pcs_clear_error(>error); - - TRACE("requeue truncate(%d) %llu@" DENTRY_FMT "\n", ireq->type, - (unsigned long long)ireq->truncreq.offset, DENTRY_ARGS(ireq->dentry)); - - ireq_delay(ireq); - continue; - } - } - ireq_complete(ireq); - } -} - void transfer_sync_data(struct pcs_cs_list * new_cs_list, struct pcs_cs_list * old_cs_list) { int i, k; diff --git a/fs/fuse/kio/pcs/pcs_req.c b/fs/fuse/kio/pcs/pcs_req.c index a05f1e43c94c..9516768c47d4 100644 --- a/fs/fuse/kio/pcs/pcs_req.c +++ b/fs/fuse/kio/pcs/pcs_req.c @@ -121,3 +121,34 @@ void ireq_handle_hole(struct pcs_int_request *ireq) ireq_complete(ireq); } + +noinline void pcs_ireq_queue_fail(struct list_head *queue, int error) +{ + while (!list_empty(queue)) { + struct pcs_int_request *ireq = list_first_entry(queue, struct pcs_int_request, list); + + list_del_init(>list); + + pcs_set_local_error(>error, error); + + if (ireq->type == PCS_IREQ_TRUNCATE) { + ireq_on_error(ireq); + + if (!(ireq->flags & IREQ_F_FATAL)) { + if (ireq_is_timed_out(ireq)) { + pcs_log(LOG_ERR, "timeout
Re: [Devel] [PATCH] fs/fuse kio_pcs: some cleanup ireq_on_error_()
On 06.06.2018 20:22, Pavel Butsykin wrote: > Signed-off-by: Pavel Butsykin Reviewed-by: Kirill Tkhai > --- > fs/fuse/kio/pcs/pcs_cluster.c | 10 +++--- > 1 file changed, 3 insertions(+), 7 deletions(-) > > diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c > index 24ec8a5f39a3..5441a357b87d 100644 > --- a/fs/fuse/kio/pcs/pcs_cluster.c > +++ b/fs/fuse/kio/pcs/pcs_cluster.c > @@ -486,11 +486,8 @@ static void ireq_on_error_(struct pcs_int_request *ireq) > case PCS_ERR_LEASE_EXPIRED: > case PCS_ERR_INTEGRITY_FAIL: { > /* TODO: tag ireq->dentry with EIO here */ > - goto fatal; > } > case PCS_ERR_CSD_LACKING: > - goto fatal; > - break; > case PCS_ERR_INV_PARAMS: > case PCS_ERR_NOT_FOUND: > case PCS_ERR_NON_EMPTY_DIR: > @@ -498,9 +495,9 @@ static void ireq_on_error_(struct pcs_int_request *ireq) > case PCS_ERR_IS_DIR: > case PCS_ERR_NO_STORAGE: > case PCS_ERR_UNAVAIL: > -fatal: > - printk(KERN_INFO "%s fatal error:%d nodeid:%llu", __func__, > -ireq->error.value, ireq->dentry->inode->nodeid); > + pr_info("%s fatal error:%d ireq->type:%d nodeid:%llu", > + __func__, ireq->error.value, ireq->type, > + ireq->dentry->inode->nodeid); > ireq->flags |= IREQ_F_FATAL; > break; > case PCS_ERR_LEASE_CONFLICT: > @@ -508,7 +505,6 @@ fatal: > break; > default: > break; > - ; > } > } > > ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel