[Devel] [PATCH 1/2] fs/fuse kio_pcs: handle error of submit_size_grow()

2018-06-07 Thread Pavel Butsykin
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

2018-06-07 Thread Pavel Butsykin
#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

2018-06-07 Thread Pavel Butsykin
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()

2018-06-07 Thread Pavel Butsykin

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_()

2018-06-07 Thread Kirill Tkhai
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