The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.47.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.46.7
------>
commit a4fdfacf2c5de6fb2b931f4a274ee878eed40660
Author: Alexey Kuznetsov <[email protected]>
Date:   Fri Apr 27 12:09:00 2018 +0300

    fuse/kio_pcs: full fallocate() support
    
    Signed-off-by: Alexey Kuznetsov <[email protected]>
    Signed-off-by: Dmitry Monakhov <[email protected]>
---
 fs/fuse/kio/pcs/fuse_io.c          | 46 ++++++++++++++++++++++++++++
 fs/fuse/kio/pcs/pcs_cluster.c      |  7 +++--
 fs/fuse/kio/pcs/pcs_cluster.h      |  1 +
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 62 +++++++++++++++++++++++++++++++++++---
 4 files changed, 108 insertions(+), 8 deletions(-)

diff --git a/fs/fuse/kio/pcs/fuse_io.c b/fs/fuse/kio/pcs/fuse_io.c
index 97802e143cb1..47950d26757f 100644
--- a/fs/fuse/kio/pcs/fuse_io.c
+++ b/fs/fuse/kio/pcs/fuse_io.c
@@ -73,6 +73,17 @@ static void on_write_done(struct pcs_fuse_req *r, off_t pos, 
size_t size)
        request_end(pfc->fc, &r->req);
 }
 
+static void on_fallocate_done(struct pcs_fuse_req *r, off_t pos, size_t size)
+{
+       struct pcs_fuse_cluster *pfc = cl_from_req(r);
+
+       DTRACE("do fuse_request_end req:%p op:%d err:%d\n", &r->req, 
r->req.in.h.opcode, r->req.out.h.error);
+       fuse_stat_account(pfc->fc, KFUSE_OP_FALLOCATE, ktime_sub(ktime_get(), 
r->exec.ireq.ts));
+       inode_dio_end(r->req.io_inode);
+
+       request_end(pfc->fc, &r->req);
+}
+
 static void req_get_iter(void *data, unsigned int offset, struct iov_iter *it)
 {
        struct pcs_fuse_req *r = data;
@@ -134,6 +145,11 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned 
short type, off_t offse
                BUG_ON(r->req.in.argbvec && r->req.in.argpages);
                set_io_buff(r, offset, size, r->req.in.argbvec, 0);
                break;
+       case PCS_REQ_T_WRITE_ZERO:
+       case PCS_REQ_T_WRITE_HOLE:
+               r->exec.io.req.pos = offset;
+               r->exec.io.req.size = size;
+               break;
        }
 
        r->exec.io.req.type = type;
@@ -176,6 +192,10 @@ static void ioreq_complete(pcs_api_iorequest_t *ioreq)
        case PCS_REQ_T_SYNC:
                on_sync_done(r);
                break;
+       case PCS_REQ_T_WRITE_HOLE:
+       case PCS_REQ_T_WRITE_ZERO:
+               on_fallocate_done(r, ioreq->pos, ioreq->size);
+               break;
        default:
                BUG();
        }
@@ -186,3 +206,29 @@ void pcs_fuse_prep_io(struct pcs_fuse_req *r, unsigned 
short type, off_t offset,
 {
        prepare_io_(r, type, offset, size, ioreq_complete);
 }
+
+static void falloc_req_complete(struct pcs_int_request *ireq)
+{
+       struct pcs_fuse_req * r = ireq->completion_data.priv;
+       struct pcs_fuse_cluster *pfc = cl_from_req(r);
+
+       BUG_ON(ireq->type != PCS_IREQ_NOOP);
+
+       DTRACE("do fuse_request_end req:%p op:%d err:%d\n", &r->req, 
r->req.in.h.opcode, r->req.out.h.error);
+       fuse_stat_account(pfc->fc, KFUSE_OP_FALLOCATE, ktime_sub(ktime_get(), 
ireq->ts));
+       inode_dio_end(r->req.io_inode);
+
+       request_end(pfc->fc, &r->req);
+}
+
+void pcs_fuse_prep_fallocate(struct pcs_fuse_req *r)
+{
+       struct pcs_int_request *ireq = &r->exec.ireq;
+
+       ireq->type = PCS_IREQ_NOOP;
+       ireq->ts = ktime_get();
+       ireq->complete_cb = falloc_req_complete;
+       ireq->completion_data.parent = 0;
+       ireq->completion_data.ctx = r;
+       ireq->completion_data.priv = r;
+}
diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c
index 8514e5ed06ce..2d988484ec94 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.c
+++ b/fs/fuse/kio/pcs/pcs_cluster.c
@@ -169,18 +169,19 @@ static noinline void __pcs_cc_process_ireq_rw(struct 
pcs_int_request *ireq)
 
 static void pcs_cc_process_ireq_ioreq(struct pcs_int_request *ireq)
 {
-
        if (ireq->apireq.req->type == PCS_REQ_T_SYNC) {
                map_inject_flush_req(ireq);
                return;
        }
        if (ireq->apireq.req->type != PCS_REQ_T_READ &&
-           ireq->apireq.req->type != PCS_REQ_T_WRITE) {
+           ireq->apireq.req->type != PCS_REQ_T_WRITE &&
+           ireq->apireq.req->type != PCS_REQ_T_WRITE_HOLE &&
+           ireq->apireq.req->type != PCS_REQ_T_WRITE_ZERO) {
                pcs_set_local_error(&ireq->error, PCS_ERR_PROTOCOL);
                ireq_complete(ireq);
+               return;
        }
        return __pcs_cc_process_ireq_rw(ireq);
-
 }
 
 static void ireq_process_(struct pcs_int_request *ireq)
diff --git a/fs/fuse/kio/pcs/pcs_cluster.h b/fs/fuse/kio/pcs/pcs_cluster.h
index 8b58d3cd946b..f1c20797d951 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.h
+++ b/fs/fuse/kio/pcs/pcs_cluster.h
@@ -102,6 +102,7 @@ int pcs_cc_init(struct pcs_cluster_core *cc, struct 
workqueue_struct *wq,
 void pcs_cc_fini(struct pcs_cluster_core *cc);
 
 void pcs_fuse_prep_io(struct pcs_fuse_req *r, unsigned short type, off_t 
offset, size_t size);
+void pcs_fuse_prep_fallocate(struct pcs_fuse_req *r);
 int fuse_pcs_csconn_send(struct fuse_conn *fc, struct pcs_rpc *ep, int flags);
 
 
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c 
b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index bae89deffde2..70a7b38e3692 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -58,9 +58,6 @@ static void process_pcs_init_reply(struct fuse_conn *fc, 
struct fuse_req *req)
                fc->conn_error = 1;
                goto out;
        }
-       /* TODO: Not yet implemented PSBM-80365 */
-       fc->no_fiemap = 1;
-       fc->no_fallocate = 1;
 
        fc->kio.ctx = pfc;
        printk("FUSE: kio_pcs: cl: " CLUSTER_ID_FMT ", clientid: " NODE_FMT 
"\n",
@@ -694,7 +691,7 @@ static void wait_grow(struct pcs_fuse_req *r, struct 
pcs_dentry_info *di, unsign
 {
        assert_spin_locked(&di->lock);
        BUG_ON(r->exec.size.waiting);
-       BUG_ON(r->req.in.h.opcode != FUSE_WRITE);
+       BUG_ON(r->req.in.h.opcode != FUSE_WRITE && r->req.in.h.opcode != 
FUSE_FALLOCATE);
 
        TRACE("insert ino:%ld->required:%lld r(%p)->required:%lld\n", 
r->req.io_inode->i_ino,
              di->size.required, r, required);
@@ -705,6 +702,7 @@ static void wait_grow(struct pcs_fuse_req *r, struct 
pcs_dentry_info *di, unsign
        if (!di->size.required)
                queue_work(pcs_wq, &di->size.work);
 }
+
 static void wait_shrink(struct pcs_fuse_req *r, struct pcs_dentry_info *di)
 {
        assert_spin_locked(&di->lock);
@@ -751,7 +749,7 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
                        size = di->fileinfo.attr.size - in->offset;
                }
                pcs_fuse_prep_io(r, PCS_REQ_T_READ, in->offset, size);
-       } else {
+       } else if (r->req.in.h.opcode == FUSE_WRITE) {
                struct fuse_write_in *in = &r->req.misc.write.in;
 
                if (in->offset + in->size > di->fileinfo.attr.size) {
@@ -759,7 +757,26 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
                        ret = 1;
                }
                pcs_fuse_prep_io(r, PCS_REQ_T_WRITE, in->offset, in->size);
+       } else {
+               struct fuse_fallocate_in const *in = r->req.in.args[0].value;
+
+               if (in->offset + in->length > di->fileinfo.attr.size) {
+                       wait_grow(r, di, in->offset + in->length);
+                       ret = 1;
+               }
 
+               if (in->mode & FALLOC_FL_PUNCH_HOLE)
+                       pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_HOLE, in->offset, 
in->length);
+               else if (in->mode & FALLOC_FL_ZERO_RANGE)
+                       pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_ZERO, in->offset, 
in->length);
+               else {
+                       if (ret) {
+                               pcs_fuse_prep_fallocate(r);
+                       } else {
+                               spin_unlock(&di->lock);
+                               return -1;
+                       }
+               }
        }
        inode_dio_begin(r->req.io_inode);
        spin_unlock(&di->lock);
@@ -796,15 +813,49 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, 
struct fuse_req *req,
                        return;
                break;
        }
+       case FUSE_FALLOCATE: {
+               int ret;
+               struct fuse_fallocate_in *inarg = (void*) req->in.args[0].value;
+
+               if (pfc->fc->no_fallocate) {
+                       r->req.out.h.error = -EOPNOTSUPP;
+                       goto error;
+               }
+
+               if (inarg->offset >= di->fileinfo.attr.size)
+                       inarg->mode &= ~FALLOC_FL_ZERO_RANGE;
+
+               if (inarg->mode & FALLOC_FL_KEEP_SIZE) {
+                       if (inarg->offset + inarg->length > 
di->fileinfo.attr.size)
+                               inarg->length = di->fileinfo.attr.size - 
inarg->offset;
+               }
+
+               if (inarg->mode & (FALLOC_FL_ZERO_RANGE|FALLOC_FL_PUNCH_HOLE)) {
+                       if ((inarg->offset & (PAGE_SIZE - 1)) || (inarg->length 
& (PAGE_SIZE - 1))) {
+                               r->req.out.h.error = -EINVAL;
+                               goto error;
+                       }
+               }
+
+               ret = pcs_fuse_prep_rw(r);
+               if (!ret)
+                       goto submit;
+               if (ret > 0)
+                       /* Pended, nothing to do. */
+                       return;
+               break;
+       }
        case FUSE_FSYNC:
                pcs_fuse_prep_io(r, PCS_REQ_T_SYNC, 0, 0);
                goto submit;
        }
        r->req.out.h.error = 0;
+error:
        DTRACE("do fuse_request_end req:%p op:%d err:%d\n", &r->req, 
r->req.in.h.opcode, r->req.out.h.error);
 
        request_end(pfc->fc, &r->req);
        return;
+
 submit:
        if (async)
                pcs_cc_submit(ireq->cc, ireq);
@@ -934,6 +985,7 @@ static int kpcs_req_send(struct fuse_conn* fc, struct 
fuse_req *req, bool bg, bo
        case FUSE_READ:
        case FUSE_WRITE:
        case FUSE_FSYNC:
+       case FUSE_FALLOCATE:
                fi = get_fuse_inode(req->io_inode);
                if (!fi->private)
                        return 1;
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to