[v2] fs/fuse kio: invalidate files for kio

Submitted by Pavel Butsykin on Jan. 21, 2019, 4:30 p.m.

Details

Message ID 20190121163022.21038-1-pbutsykin@virtuozzo.com
State New
Series "fs/fuse kio: invalidate files for kio"
Headers show

Commit Message

Pavel Butsykin Jan. 21, 2019, 4:30 p.m.
Make fuse_invalidate_files() work for kio. This is necessary to maintain
vstorage revoke in FPath mode. To do this, let's add a list of inflight kio
requests to be able to handle this list in fuse_invalidate_files(). The list
will also be useful to implement the full-featured .vstorage.info and
fuse_abort_conn() for kio.

#VSTOR-19620

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 fs/fuse/fuse_i.h                   |  4 ++++
 fs/fuse/inode.c                    |  8 ++++++--
 fs/fuse/kio/pcs/fuse_io.c          |  5 +++++
 fs/fuse/kio/pcs/pcs_client_types.h |  2 ++
 fs/fuse/kio/pcs/pcs_cluster.h      |  7 +++++++
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 27 +++++++++++++++++++++++++++
 6 files changed, 51 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4c27bfa0e74d..0914940d6735 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -528,6 +528,7 @@  struct fuse_kio_ops {
 	int  (*file_open)(struct fuse_conn *fc, struct file *file,
 			  struct inode *inode);
 	void (*inode_release)(struct fuse_inode *fi);
+	void (*kill_requests)(struct fuse_conn *fc, struct inode *inode);
 
 };
 int fuse_register_kio(struct fuse_kio_ops *ops);
@@ -1107,4 +1108,7 @@  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);
 
+void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
+			struct list_head *req_list);
+
 #endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 34e52262d37e..cb275ff21991 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -369,8 +369,8 @@  int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
 	return 0;
 }
 
-static void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
-			       struct list_head *req_list)
+void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
+			struct list_head *req_list)
 {
 	struct fuse_req *req;
 
@@ -393,6 +393,7 @@  static void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
 			req->num_pages = 0;
 		}
 }
+EXPORT_SYMBOL_GPL(fuse_kill_requests);
 
 int fuse_invalidate_files(struct fuse_conn *fc, u64 nodeid)
 {
@@ -442,6 +443,9 @@  int fuse_invalidate_files(struct fuse_conn *fc, u64 nodeid)
 		}
 		fuse_kill_requests(fc, inode, &fc->main_iq.pending);
 		fuse_kill_requests(fc, inode, &fc->bg_queue);
+		if (fc->kio.op && fc->kio.op->kill_requests)
+			fc->kio.op->kill_requests(fc, inode);
+
 		wake_up(&fi->page_waitq); /* readpage[s] can wait on fuse wb */
 		spin_unlock(&fc->lock);
 
diff --git a/fs/fuse/kio/pcs/fuse_io.c b/fs/fuse/kio/pcs/fuse_io.c
index 61a2e7f1eac6..219f4e3423af 100644
--- a/fs/fuse/kio/pcs/fuse_io.c
+++ b/fs/fuse/kio/pcs/fuse_io.c
@@ -205,6 +205,7 @@  static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
 static void ioreq_complete(pcs_api_iorequest_t *ioreq)
 {
 	struct pcs_fuse_req *r = ioreq->datasource;
+	struct pcs_dentry_info *di = get_pcs_inode(r->req.io_inode);
 
 	BUG_ON(ioreq != &r->exec.io.req);
 
@@ -217,6 +218,10 @@  static void ioreq_complete(pcs_api_iorequest_t *ioreq)
 		r->req.out.h.error = 0;
 	}
 
+	spin_lock(&di->kq_lock);
+	list_del_init(&r->req.list);
+	spin_unlock(&di->kq_lock);
+
 	switch (ioreq->type) {
 	case PCS_REQ_T_READ:
 		on_read_done(r, ioreq->size);
diff --git a/fs/fuse/kio/pcs/pcs_client_types.h b/fs/fuse/kio/pcs/pcs_client_types.h
index 9ddce5cff3f5..1be32cbbf285 100644
--- a/fs/fuse/kio/pcs/pcs_client_types.h
+++ b/fs/fuse/kio/pcs/pcs_client_types.h
@@ -68,6 +68,8 @@  struct pcs_dentry_info {
 		size_op_t op;
 	} size;
 	struct fuse_inode	*inode;
+	struct list_head	kq;
+	spinlock_t		kq_lock;
 };
 
 static inline void pcs_clear_fileinfo(struct pcs_dentry_info *i)
diff --git a/fs/fuse/kio/pcs/pcs_cluster.h b/fs/fuse/kio/pcs/pcs_cluster.h
index 9c537cb43b30..73af9359706e 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.h
+++ b/fs/fuse/kio/pcs/pcs_cluster.h
@@ -78,6 +78,13 @@  static inline struct pcs_dentry_info *pcs_inode_from_fuse(struct fuse_inode *fi)
 	return (struct pcs_dentry_info *)fi->private;
 }
 
+static inline struct pcs_dentry_info *get_pcs_inode(struct inode *inode)
+{
+	struct fuse_inode *fi = get_fuse_inode(inode);
+
+	return pcs_inode_from_fuse(fi);
+}
+
 static inline struct pcs_fuse_cluster *cl_from_req(struct pcs_fuse_req *r)
 {
 	return pcs_cluster_from_cc(r->exec.ireq.cc);
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index cdd4fe578128..da4b5fba03fb 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -341,6 +341,8 @@  static int kpcs_do_file_open(struct fuse_conn *fc, struct file *file, struct ino
 	pcs_set_fileinfo(di, &info);
 	di->cluster = &pfc->cc;
 	di->inode = fi;
+	INIT_LIST_HEAD(&di->kq);
+	spin_lock_init(&di->kq_lock);
 	TRACE("init id:%llu chunk_size:%d stripe_depth:%d strip_width:%d\n",
 	      fi->nodeid, di->fileinfo.sys.chunk_size,
 	      di->fileinfo.sys.stripe_depth, di->fileinfo.sys.strip_width);
@@ -983,6 +985,10 @@  error:
 	return;
 
 submit:
+	spin_lock(&di->kq_lock);
+	list_add_tail(&req->list, &di->kq);
+	spin_unlock(&di->kq_lock);
+
 	if (async)
 		pcs_cc_submit(ireq->cc, ireq);
 	else
@@ -1488,6 +1494,26 @@  void __kfuse_trace(struct fuse_conn * fc, unsigned long ip, const char * fmt, ..
 	put_cpu();
 }
 
+static void kpcs_kill_requests(struct fuse_conn *fc, struct inode *inode)
+{
+	struct fuse_file *ff;
+
+	assert_spin_locked(&fc->lock);
+
+	list_for_each_entry(ff, &fc->conn_files, fl) {
+		struct pcs_dentry_info *di;
+
+		if (!ff->ff_dentry)
+			continue;
+
+		di = get_pcs_inode(ff->ff_dentry->d_inode);
+
+		spin_lock(&di->kq_lock);
+		fuse_kill_requests(fc, inode, &di->kq);
+		spin_unlock(&di->kq_lock);
+	}
+}
+
 static struct fuse_kio_ops kio_pcs_ops = {
 	.name		= "pcs",
 	.owner		= THIS_MODULE,
@@ -1500,6 +1526,7 @@  static struct fuse_kio_ops kio_pcs_ops = {
 	.req_send	= kpcs_req_send,
 	.file_open	= kpcs_file_open,
 	.inode_release	= kpcs_inode_release,
+	.kill_requests	= kpcs_kill_requests,
 };
 
 

Comments

Alexey Kuznetsov Jan. 23, 2019, 4:47 p.m.
Ack

On Mon, Jan 21, 2019 at 7:30 PM Pavel Butsykin <pbutsykin@virtuozzo.com> wrote:
>
> Make fuse_invalidate_files() work for kio. This is necessary to maintain
> vstorage revoke in FPath mode. To do this, let's add a list of inflight kio
> requests to be able to handle this list in fuse_invalidate_files(). The list
> will also be useful to implement the full-featured .vstorage.info and
> fuse_abort_conn() for kio.
>
> #VSTOR-19620
>
> Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
> ---
>  fs/fuse/fuse_i.h                   |  4 ++++
>  fs/fuse/inode.c                    |  8 ++++++--
>  fs/fuse/kio/pcs/fuse_io.c          |  5 +++++
>  fs/fuse/kio/pcs/pcs_client_types.h |  2 ++
>  fs/fuse/kio/pcs/pcs_cluster.h      |  7 +++++++
>  fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 27 +++++++++++++++++++++++++++
>  6 files changed, 51 insertions(+), 2 deletions(-)
>
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 4c27bfa0e74d..0914940d6735 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -528,6 +528,7 @@ struct fuse_kio_ops {
>         int  (*file_open)(struct fuse_conn *fc, struct file *file,
>                           struct inode *inode);
>         void (*inode_release)(struct fuse_inode *fi);
> +       void (*kill_requests)(struct fuse_conn *fc, struct inode *inode);
>
>  };
>  int fuse_register_kio(struct fuse_kio_ops *ops);
> @@ -1107,4 +1108,7 @@ 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);
>
> +void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
> +                       struct list_head *req_list);
> +
>  #endif /* _FS_FUSE_I_H */
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 34e52262d37e..cb275ff21991 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -369,8 +369,8 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
>         return 0;
>  }
>
> -static void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
> -                              struct list_head *req_list)
> +void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
> +                       struct list_head *req_list)
>  {
>         struct fuse_req *req;
>
> @@ -393,6 +393,7 @@ static void fuse_kill_requests(struct fuse_conn *fc, struct inode *inode,
>                         req->num_pages = 0;
>                 }
>  }
> +EXPORT_SYMBOL_GPL(fuse_kill_requests);
>
>  int fuse_invalidate_files(struct fuse_conn *fc, u64 nodeid)
>  {
> @@ -442,6 +443,9 @@ int fuse_invalidate_files(struct fuse_conn *fc, u64 nodeid)
>                 }
>                 fuse_kill_requests(fc, inode, &fc->main_iq.pending);
>                 fuse_kill_requests(fc, inode, &fc->bg_queue);
> +               if (fc->kio.op && fc->kio.op->kill_requests)
> +                       fc->kio.op->kill_requests(fc, inode);
> +
>                 wake_up(&fi->page_waitq); /* readpage[s] can wait on fuse wb */
>                 spin_unlock(&fc->lock);
>
> diff --git a/fs/fuse/kio/pcs/fuse_io.c b/fs/fuse/kio/pcs/fuse_io.c
> index 61a2e7f1eac6..219f4e3423af 100644
> --- a/fs/fuse/kio/pcs/fuse_io.c
> +++ b/fs/fuse/kio/pcs/fuse_io.c
> @@ -205,6 +205,7 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
>  static void ioreq_complete(pcs_api_iorequest_t *ioreq)
>  {
>         struct pcs_fuse_req *r = ioreq->datasource;
> +       struct pcs_dentry_info *di = get_pcs_inode(r->req.io_inode);
>
>         BUG_ON(ioreq != &r->exec.io.req);
>
> @@ -217,6 +218,10 @@ static void ioreq_complete(pcs_api_iorequest_t *ioreq)
>                 r->req.out.h.error = 0;
>         }
>
> +       spin_lock(&di->kq_lock);
> +       list_del_init(&r->req.list);
> +       spin_unlock(&di->kq_lock);
> +
>         switch (ioreq->type) {
>         case PCS_REQ_T_READ:
>                 on_read_done(r, ioreq->size);
> diff --git a/fs/fuse/kio/pcs/pcs_client_types.h b/fs/fuse/kio/pcs/pcs_client_types.h
> index 9ddce5cff3f5..1be32cbbf285 100644
> --- a/fs/fuse/kio/pcs/pcs_client_types.h
> +++ b/fs/fuse/kio/pcs/pcs_client_types.h
> @@ -68,6 +68,8 @@ struct pcs_dentry_info {
>                 size_op_t op;
>         } size;
>         struct fuse_inode       *inode;
> +       struct list_head        kq;
> +       spinlock_t              kq_lock;
>  };
>
>  static inline void pcs_clear_fileinfo(struct pcs_dentry_info *i)
> diff --git a/fs/fuse/kio/pcs/pcs_cluster.h b/fs/fuse/kio/pcs/pcs_cluster.h
> index 9c537cb43b30..73af9359706e 100644
> --- a/fs/fuse/kio/pcs/pcs_cluster.h
> +++ b/fs/fuse/kio/pcs/pcs_cluster.h
> @@ -78,6 +78,13 @@ static inline struct pcs_dentry_info *pcs_inode_from_fuse(struct fuse_inode *fi)
>         return (struct pcs_dentry_info *)fi->private;
>  }
>
> +static inline struct pcs_dentry_info *get_pcs_inode(struct inode *inode)
> +{
> +       struct fuse_inode *fi = get_fuse_inode(inode);
> +
> +       return pcs_inode_from_fuse(fi);
> +}
> +
>  static inline struct pcs_fuse_cluster *cl_from_req(struct pcs_fuse_req *r)
>  {
>         return pcs_cluster_from_cc(r->exec.ireq.cc);
> diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
> index cdd4fe578128..da4b5fba03fb 100644
> --- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
> +++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
> @@ -341,6 +341,8 @@ static int kpcs_do_file_open(struct fuse_conn *fc, struct file *file, struct ino
>         pcs_set_fileinfo(di, &info);
>         di->cluster = &pfc->cc;
>         di->inode = fi;
> +       INIT_LIST_HEAD(&di->kq);
> +       spin_lock_init(&di->kq_lock);
>         TRACE("init id:%llu chunk_size:%d stripe_depth:%d strip_width:%d\n",
>               fi->nodeid, di->fileinfo.sys.chunk_size,
>               di->fileinfo.sys.stripe_depth, di->fileinfo.sys.strip_width);
> @@ -983,6 +985,10 @@ error:
>         return;
>
>  submit:
> +       spin_lock(&di->kq_lock);
> +       list_add_tail(&req->list, &di->kq);
> +       spin_unlock(&di->kq_lock);
> +
>         if (async)
>                 pcs_cc_submit(ireq->cc, ireq);
>         else
> @@ -1488,6 +1494,26 @@ void __kfuse_trace(struct fuse_conn * fc, unsigned long ip, const char * fmt, ..
>         put_cpu();
>  }
>
> +static void kpcs_kill_requests(struct fuse_conn *fc, struct inode *inode)
> +{
> +       struct fuse_file *ff;
> +
> +       assert_spin_locked(&fc->lock);
> +
> +       list_for_each_entry(ff, &fc->conn_files, fl) {
> +               struct pcs_dentry_info *di;
> +
> +               if (!ff->ff_dentry)
> +                       continue;
> +
> +               di = get_pcs_inode(ff->ff_dentry->d_inode);
> +
> +               spin_lock(&di->kq_lock);
> +               fuse_kill_requests(fc, inode, &di->kq);
> +               spin_unlock(&di->kq_lock);
> +       }
> +}
> +
>  static struct fuse_kio_ops kio_pcs_ops = {
>         .name           = "pcs",
>         .owner          = THIS_MODULE,
> @@ -1500,6 +1526,7 @@ static struct fuse_kio_ops kio_pcs_ops = {
>         .req_send       = kpcs_req_send,
>         .file_open      = kpcs_file_open,
>         .inode_release  = kpcs_inode_release,
> +       .kill_requests  = kpcs_kill_requests,
>  };
>
>
> --
> 2.15.1
>