[Devel] [PATCH RHEL7 COMMIT] fuse/kio_pcs: FIEMAP support
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Apr 27 12:09:01 MSK 2018
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 9227091012d80d24aecbbae42c13c3510e73d4c4
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date: Fri Apr 27 12:09:01 2018 +0300
fuse/kio_pcs: FIEMAP support
Signed-off-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
---
fs/fuse/file.c | 1 +
fs/fuse/kio/pcs/fuse_io.c | 42 +++++++-
fs/fuse/kio/pcs/pcs_cluster.c | 207 +++++++++++++++++++++++++++++++++++++
fs/fuse/kio/pcs/pcs_cluster.h | 2 +-
fs/fuse/kio/pcs/pcs_cs.c | 22 +++-
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 63 ++++++++---
fs/fuse/kio/pcs/pcs_map.c | 28 +++--
fs/fuse/kio/pcs/pcs_req.c | 6 ++
fs/fuse/kio/pcs/pcs_req.h | 1 +
9 files changed, 344 insertions(+), 28 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 43733920fd7e..d84dd402c83c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3794,6 +3794,7 @@ static int fuse_request_fiemap(struct inode *inode, u32 cur_max,
if (IS_ERR(req))
return PTR_ERR(req);
+ req->io_inode = inode;
req->in.h.opcode = FUSE_IOCTL;
req->in.h.nodeid = get_node_id(inode);
diff --git a/fs/fuse/kio/pcs/fuse_io.c b/fs/fuse/kio/pcs/fuse_io.c
index 47950d26757f..65c4a1881d89 100644
--- a/fs/fuse/kio/pcs/fuse_io.c
+++ b/fs/fuse/kio/pcs/fuse_io.c
@@ -84,6 +84,16 @@ static void on_fallocate_done(struct pcs_fuse_req *r, off_t pos, size_t size)
request_end(pfc->fc, &r->req);
}
+static void on_fiemap_done(struct pcs_fuse_req *r)
+{
+ 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);
+
+ 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;
@@ -92,6 +102,22 @@ static void req_get_iter(void *data, unsigned int offset, struct iov_iter *it)
iov_iter_advance(it, offset);
}
+static void req_fiemap_get_iter(void *data, unsigned int offset, struct iov_iter *it)
+{
+ struct pcs_fuse_req * r = data;
+ struct pcs_int_request *ireq = &r->exec.ireq;
+
+ if (offset < sizeof(struct fiemap)) {
+ iov_iter_init_plain(it, (char *)r->req.out.args[1].value,
+ sizeof(struct fiemap), 0);
+ } else {
+ offset -= sizeof(struct fiemap);
+ iov_iter_init_bvec(it, r->exec.io.bvec, r->exec.io.num_bvecs,
+ ireq->apireq.aux*sizeof(struct fiemap_extent), 0);
+ }
+ iov_iter_advance(it, offset);
+}
+
static inline void set_io_buff(struct pcs_fuse_req *r, off_t offset, size_t size,
int is_bvec, int zeroing)
{
@@ -126,7 +152,7 @@ static inline void set_io_buff(struct pcs_fuse_req *r, off_t offset, size_t size
r->exec.io.req.size = size;
}
-static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size,
+static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size, u64 aux,
void (*complete)(struct _pcs_api_iorequest_t *))
{
/* Use inline request structure */
@@ -150,6 +176,9 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
r->exec.io.req.pos = offset;
r->exec.io.req.size = size;
break;
+ case PCS_REQ_T_FIEMAP:
+ set_io_buff(r, offset, size, 0, 0);
+ break;
}
r->exec.io.req.type = type;
@@ -157,10 +186,14 @@ static void prepare_io_(struct pcs_fuse_req *r, unsigned short type, off_t offse
r->exec.io.req.get_iter = req_get_iter;
r->exec.io.req.complete = complete;
+ if (type == PCS_REQ_T_FIEMAP)
+ r->exec.io.req.get_iter = req_fiemap_get_iter;
+
/* Initialize internal request structure */
ireq->type = PCS_IREQ_API;
ireq->ts = ktime_get();
ireq->apireq.req = &r->exec.io.req;
+ ireq->apireq.aux = aux;
ireq->complete_cb = intreq_complete;
ireq->completion_data.parent = 0;
ireq->completion_data.ctx = r;
@@ -196,15 +229,18 @@ static void ioreq_complete(pcs_api_iorequest_t *ioreq)
case PCS_REQ_T_WRITE_ZERO:
on_fallocate_done(r, ioreq->pos, ioreq->size);
break;
+ case PCS_REQ_T_FIEMAP:
+ on_fiemap_done(r);
+ break;
default:
BUG();
}
}
-void pcs_fuse_prep_io(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size)
+void pcs_fuse_prep_io(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size, u64 aux)
{
- prepare_io_(r, type, offset, size, ioreq_complete);
+ prepare_io_(r, type, offset, size, aux, ioreq_complete);
}
static void falloc_req_complete(struct pcs_int_request *ireq)
diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c
index 2d988484ec94..b995135a35cc 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.c
+++ b/fs/fuse/kio/pcs/pcs_cluster.c
@@ -3,6 +3,7 @@
#include <linux/kthread.h>
#include <linux/types.h>
#include <linux/rbtree.h>
+#include <linux/highmem.h>
#include "pcs_types.h"
#include "pcs_sock_io.h"
@@ -16,6 +17,8 @@
#include "../../fuse_i.h"
+void pcs_cc_process_ireq_chunk(struct pcs_int_request *ireq);
+
static inline int is_file_inline(struct pcs_dentry_info *di)
{
return di->fileinfo.attr.attrib & PCS_FATTR_INLINE;
@@ -75,6 +78,192 @@ void pcs_sreq_complete(struct pcs_int_request *sreq)
ireq_destroy(sreq);
}
+struct fiemap_iterator
+{
+ struct pcs_int_request *orig_ireq;
+ wait_queue_head_t wq;
+ char *buffer;
+ unsigned int fiemap_max;
+ u32 *mapped;
+
+ struct pcs_int_request ireq;
+ pcs_api_iorequest_t apireq;
+};
+
+static void fiemap_iter_done(struct pcs_int_request * ireq)
+{
+ struct fiemap_iterator * fiter = container_of(ireq, struct fiemap_iterator, ireq);
+
+ wake_up(&fiter->wq);
+}
+
+static void fiemap_get_iter(void * datasource, unsigned int offset, struct iov_iter *it)
+{
+ struct fiemap_iterator * iter = datasource;
+
+ BUG_ON(offset >= PCS_FIEMAP_BUFSIZE);
+ iov_iter_init_plain(it, iter->buffer, PCS_FIEMAP_BUFSIZE, 0);
+ iov_iter_advance(it, offset);
+}
+
+static void xfer_fiemap_extents(struct fiemap_iterator * iter, u64 pos, char * buffer, unsigned int count)
+{
+ struct pcs_cs_fiemap_rec * r = (struct pcs_cs_fiemap_rec *)buffer;
+
+ BUG_ON(count % sizeof(struct pcs_cs_fiemap_rec));
+ count /= sizeof(struct pcs_cs_fiemap_rec);
+
+ if (r[count - 1].flags & PCS_CS_FIEMAP_FL_OVFL) {
+ /* Adjust next scan pos in case of overflow, overwriting size */
+ u64 end = iter->apireq.pos + r[count - 1].offset + r[count - 1].size;
+ if (end < pos + iter->apireq.size) {
+ u64 adjusted_size = end - pos;
+ if (adjusted_size < iter->apireq.size)
+ iter->apireq.size = adjusted_size;
+ }
+ }
+
+ if (iter->fiemap_max == 0) {
+ *iter->mapped += count;
+ } else {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ struct fiemap_extent e;
+ struct iov_iter it;
+ void * buf;
+ size_t len;
+
+ if (*iter->mapped >= iter->fiemap_max)
+ return;
+
+ memset(&e, 0, sizeof(e));
+ e.fe_logical = e.fe_physical = iter->apireq.pos + r[i].offset;
+ e.fe_length = r[i].size;
+ if (r[i].flags & PCS_CS_FIEMAP_FL_ZERO)
+ e.fe_flags |= FIEMAP_EXTENT_UNWRITTEN;
+ if (r[i].flags & PCS_CS_FIEMAP_FL_CACHE)
+ e.fe_flags |= FIEMAP_EXTENT_DELALLOC;
+
+ iter->orig_ireq->apireq.req->get_iter(iter->orig_ireq->apireq.req->datasource,
+ offsetof(struct fiemap, fm_extents) +
+ *iter->mapped * sizeof(struct fiemap_extent),
+ &it);
+ iov_iter_truncate(&it, sizeof(e));
+
+ iov_iter_kmap_atomic(&it, &buf, &len);
+ memcpy(buf, &e, len);
+ kunmap_atomic(buf);
+ if (len != sizeof(e)) {
+ size_t fraglen;
+ iov_iter_advance(&it, len);
+ iov_iter_kmap_atomic(&it, &buf, &fraglen);
+ BUG_ON(len + fraglen != sizeof(e));
+ memcpy(buf, (char*)&e + len, fraglen);
+ kunmap_atomic(buf);
+ }
+ (*iter->mapped)++;
+ }
+ }
+}
+
+static int fiemap_worker(void * arg)
+{
+ struct pcs_int_request * orig_ireq = arg;
+ struct pcs_dentry_info * di;
+ struct fiemap_iterator * fiter;
+ struct iov_iter it;
+ u64 pos, end;
+
+ fiter = kmalloc(sizeof(struct fiemap_iterator), GFP_KERNEL);
+ if (fiter == NULL) {
+ pcs_set_local_error(&orig_ireq->error, PCS_ERR_NOMEM);
+ ireq_complete(orig_ireq);
+ return 0;
+ }
+
+ fiter->orig_ireq = orig_ireq;
+ init_waitqueue_head(&fiter->wq);
+ di = orig_ireq->dentry;
+ ireq_init(di, &fiter->ireq);
+ fiter->ireq.type = PCS_IREQ_API;
+ fiter->ireq.apireq.req = &fiter->apireq;
+ fiter->ireq.completion_data.parent = NULL;
+ fiter->ireq.complete_cb = fiemap_iter_done;
+ fiter->apireq.datasource = fiter;
+ fiter->apireq.get_iter = fiemap_get_iter;
+ fiter->apireq.complete = NULL;
+ fiter->buffer = kvmalloc(PCS_FIEMAP_BUFSIZE, GFP_KERNEL);
+ if (fiter->buffer == NULL) {
+ pcs_set_local_error(&orig_ireq->error, PCS_ERR_NOMEM);
+ ireq_complete(orig_ireq);
+ kfree(fiter);
+ return 0;
+ }
+ fiter->fiemap_max = orig_ireq->apireq.aux;
+ orig_ireq->apireq.req->get_iter(orig_ireq->apireq.req->datasource, 0, &it);
+ fiter->mapped = &((struct fiemap*)it.data)->fm_mapped_extents;
+
+ pos = fiter->orig_ireq->apireq.req->pos;
+ end = pos + fiter->orig_ireq->apireq.req->size;
+ while (pos < end) {
+ struct pcs_int_request * sreq;
+
+ if (fiter->fiemap_max && *fiter->mapped >= fiter->fiemap_max)
+ break;
+
+ fiter->apireq.pos = pos;
+ fiter->apireq.size = end - pos;
+ fiter->ireq.ts = ktime_get();
+
+ sreq = ireq_alloc(di);
+ if (!sreq) {
+ pcs_set_local_error(&orig_ireq->error, PCS_ERR_NOMEM);
+ goto out;
+ }
+
+ atomic_set(&fiter->ireq.iocount, 0);
+
+ sreq->dentry = di;
+ sreq->type = PCS_IREQ_IOCHUNK;
+ sreq->iochunk.map = NULL;
+ sreq->iochunk.flow = pcs_flow_record(&di->mapping.ftab, 0, pos, end-pos, &di->cluster->maps.ftab);
+ sreq->iochunk.cmd = PCS_REQ_T_FIEMAP;
+ sreq->iochunk.cs_index = 0;
+ sreq->iochunk.chunk = pos;
+ sreq->iochunk.offset = 0;
+ sreq->iochunk.dio_offset = 0;
+ sreq->iochunk.size = end - pos;
+ sreq->iochunk.csl = NULL;
+ sreq->iochunk.banned_cs.val = 0;
+ sreq->iochunk.msg.destructor = NULL;
+ sreq->iochunk.msg.rpc = NULL;
+
+ pcs_sreq_attach(sreq, &fiter->ireq);
+ sreq->complete_cb = pcs_sreq_complete;
+
+ pcs_cc_process_ireq_chunk(sreq);
+
+ wait_event(fiter->wq, atomic_read(&fiter->ireq.iocount) == 0);
+
+ if (pcs_if_error(&fiter->ireq.error)) {
+ fiter->orig_ireq->error = fiter->ireq.error;
+ goto out;
+ }
+
+ if (fiter->ireq.apireq.aux)
+ xfer_fiemap_extents(fiter, pos, fiter->buffer, fiter->ireq.apireq.aux);
+
+ pos += fiter->apireq.size;
+ }
+
+out:
+ kvfree(fiter->buffer);
+ kfree(fiter);
+ ireq_complete(orig_ireq);
+ return 0;
+}
+
void pcs_cc_process_ireq_chunk(struct pcs_int_request *ireq)
{
struct pcs_map_entry *map;
@@ -167,12 +356,30 @@ static noinline void __pcs_cc_process_ireq_rw(struct pcs_int_request *ireq)
ireq_complete(ireq);
}
+static void process_ireq_fiemap(struct pcs_int_request * ireq)
+{
+ struct task_struct * tsk;
+
+ tsk = kthread_run(fiemap_worker, ireq, "fiemap-worker");
+
+ if (IS_ERR(tsk)) {
+ pcs_set_local_error(&ireq->error, PCS_ERR_NOMEM);
+ ireq_complete(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_FIEMAP) {
+ process_ireq_fiemap(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_HOLE &&
diff --git a/fs/fuse/kio/pcs/pcs_cluster.h b/fs/fuse/kio/pcs/pcs_cluster.h
index f1c20797d951..0f13345f919f 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.h
+++ b/fs/fuse/kio/pcs/pcs_cluster.h
@@ -101,7 +101,7 @@ int pcs_cc_init(struct pcs_cluster_core *cc, struct workqueue_struct *wq,
const char *cluster_name, struct pcs_cluster_core_attr *attr);
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_io(struct pcs_fuse_req *r, unsigned short type, off_t offset, size_t size, u64 aux);
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_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index 1fecaeaff16b..ba3c0fea5fe4 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -317,6 +317,7 @@ void pcs_cs_update_stat(struct pcs_cs *cs, u32 iolat, u32 netlat, int op_type)
static void cs_response_done(struct pcs_msg *msg)
{
struct pcs_int_request *ireq = ireq_from_msg(msg);
+ unsigned int resp_size = 0;
if (!pcs_if_error(&msg->error)) {
struct pcs_cs_iohdr *h = (struct pcs_cs_iohdr *)msg_inline_head(msg->response);
@@ -324,6 +325,8 @@ static void cs_response_done(struct pcs_msg *msg)
if (h->sync.misc & PCS_CS_IO_CACHED)
ireq->flags |= IREQ_F_CACHED;
+ resp_size = h->hdr.len - sizeof(struct pcs_cs_iohdr);
+
pcs_map_verify_sync_state(ireq->dentry, ireq, msg);
} else {
TRACE(XID_FMT " IO error %d %lu : %llu:%u+%u\n", XID_ARGS(ireq->iochunk.hbuf.hdr.xid),
@@ -336,6 +339,10 @@ static void cs_response_done(struct pcs_msg *msg)
pcs_rpc_put(msg->rpc);
msg->rpc = NULL;
}
+ if (ireq->type == PCS_IREQ_IOCHUNK && ireq->iochunk.cmd == PCS_REQ_T_FIEMAP) {
+ ireq->completion_data.parent->apireq.aux = resp_size;
+ ireq->completion_data.parent->apireq.req->pos = ireq->iochunk.chunk;
+ }
ireq_complete(ireq);
}
@@ -360,7 +367,7 @@ static void cs_get_read_response_iter(struct pcs_msg *msg, int offset, struct io
offset -= (unsigned int)sizeof(struct pcs_cs_iohdr);
ar->get_iter(ar->datasource, ireq->iochunk.dio_offset, it);
- iov_iter_truncate(it, ireq->iochunk.size);
+ iov_iter_truncate(it, msg->size - sizeof(struct pcs_cs_iohdr));
iov_iter_advance(it, offset);
TRACE("return msg:%p->size:%d off:%d it_len:%ld\n\n", msg, msg->size, offset, iov_iter_count(it));
@@ -384,6 +391,7 @@ static struct pcs_msg *cs_get_hdr(struct pcs_rpc *ep, struct pcs_rpc_hdr *h)
{
struct pcs_msg *msg, *resp;
struct pcs_rpc_hdr *req_h;
+ struct pcs_int_request *ireq;
if (!RPC_IS_RESPONSE(h->type))
return NULL;
@@ -401,6 +409,18 @@ static struct pcs_msg *cs_get_hdr(struct pcs_rpc *ep, struct pcs_rpc_hdr *h)
if (req_h->type != (h->type & ~PCS_RPC_DIRECTION))
return NULL;
+ ireq = msg->private2;
+ if (ireq->type != PCS_IREQ_IOCHUNK)
+ return NULL;
+ if (ireq->iochunk.cmd == PCS_REQ_T_READ) {
+ if (ireq->iochunk.size + sizeof(struct pcs_cs_iohdr) != msg->size)
+ return NULL;
+ } else if (ireq->iochunk.cmd == PCS_REQ_T_FIEMAP) {
+ if (PCS_FIEMAP_BUFSIZE + sizeof(struct pcs_cs_iohdr) < msg->size)
+ return NULL;
+ } else
+ return NULL;
+
resp = pcs_rpc_alloc_input_msg(ep, sizeof(struct pcs_cs_iohdr));
if (!resp)
return NULL;
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 70a7b38e3692..c371fe0ef51f 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -748,7 +748,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);
+ pcs_fuse_prep_io(r, PCS_REQ_T_READ, in->offset, size, 0);
} else if (r->req.in.h.opcode == FUSE_WRITE) {
struct fuse_write_in *in = &r->req.misc.write.in;
@@ -756,7 +756,26 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
wait_grow(r, di, in->offset + in->size);
ret = 1;
}
- pcs_fuse_prep_io(r, PCS_REQ_T_WRITE, in->offset, in->size);
+ pcs_fuse_prep_io(r, PCS_REQ_T_WRITE, in->offset, in->size, 0);
+ } else if (r->req.in.h.opcode == FUSE_IOCTL) {
+ size_t size;
+ struct fiemap const *in = r->req.in.args[1].value;
+ struct fiemap *out = r->req.out.args[1].value;
+
+ *out = *in;
+ out->fm_mapped_extents = 0;
+
+ size = in->fm_length;
+ if (in->fm_start + size > di->fileinfo.attr.size) {
+ if (in->fm_start >= di->fileinfo.attr.size) {
+ spin_unlock(&di->lock);
+ return -1;
+ }
+ size = di->fileinfo.attr.size - in->fm_start;
+ }
+ pcs_fuse_prep_io(r, PCS_REQ_T_FIEMAP, in->fm_start, in->fm_extent_count*sizeof(struct fiemap_extent),
+ in->fm_extent_count);
+ r->exec.io.req.size = size;
} else {
struct fuse_fallocate_in const *in = r->req.in.args[0].value;
@@ -766,9 +785,9 @@ static int pcs_fuse_prep_rw(struct pcs_fuse_req *r)
}
if (in->mode & FALLOC_FL_PUNCH_HOLE)
- pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_HOLE, in->offset, in->length);
+ pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_HOLE, in->offset, in->length, 0);
else if (in->mode & FALLOC_FL_ZERO_RANGE)
- pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_ZERO, in->offset, in->length);
+ pcs_fuse_prep_io(r, PCS_REQ_T_WRITE_ZERO, in->offset, in->length, 0);
else {
if (ret) {
pcs_fuse_prep_fallocate(r);
@@ -846,8 +865,24 @@ static void pcs_fuse_submit(struct pcs_fuse_cluster *pfc, struct fuse_req *req,
break;
}
case FUSE_FSYNC:
- pcs_fuse_prep_io(r, PCS_REQ_T_SYNC, 0, 0);
+ pcs_fuse_prep_io(r, PCS_REQ_T_SYNC, 0, 0, 0);
goto submit;
+ case FUSE_IOCTL: {
+ int ret;
+
+ if (pfc->fc->no_fiemap) {
+ r->req.out.h.error = -EOPNOTSUPP;
+ goto error;
+ }
+
+ ret = pcs_fuse_prep_rw(r);
+ if (!ret)
+ goto submit;
+ if (ret > 0)
+ /* Pended, nothing to do. */
+ return;
+ break;
+ }
}
r->req.out.h.error = 0;
error:
@@ -926,6 +961,7 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
{
struct pcs_fuse_cluster *pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
struct fuse_inode *fi = get_fuse_inode(req->io_inode);
+
if (!fc->initialized || fc->conn_error)
return 1;
@@ -946,6 +982,10 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
spin_unlock(&fc->lock);
return 1;
}
+
+ if (!fi || !fi->private)
+ return 1;
+
switch (req->in.h.opcode) {
case FUSE_SETATTR: {
struct pcs_fuse_req *r = pcs_req_from_fuse(req);
@@ -953,10 +993,6 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
struct pcs_dentry_info *di;
int shrink = 0;
- /* Skip speciall inodes */
- if (!fi->private)
- return 1;
-
if (!(inarg->valid & FATTR_SIZE))
return 1;
@@ -986,16 +1022,19 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
case FUSE_WRITE:
case FUSE_FSYNC:
case FUSE_FALLOCATE:
- fi = get_fuse_inode(req->io_inode);
- if (!fi->private)
+ break;
+ case FUSE_IOCTL: {
+ struct fuse_ioctl_in const * inarg = req->in.args[0].value;
+
+ if (inarg->cmd != FS_IOC_FIEMAP)
return 1;
break;
+ }
default:
return 1;
}
-
__clear_bit(FR_BACKGROUND, &req->flags);
__clear_bit(FR_PENDING, &req->flags);
/* request_end below will do fuse_put_request() */
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 65b71c69ec8d..705743056462 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -2204,17 +2204,23 @@ void map_submit(struct pcs_map_entry * m, struct pcs_int_request *ireq, int requ
BUG_ON(ireq->iochunk.chunk != map_chunk_start(m));
BUG_ON(ireq->iochunk.offset != pos - ireq->iochunk.chunk);
if (ireq->iochunk.size > len) {
- struct pcs_int_request * sreq;
-
- sreq = pcs_ireq_split(ireq, len, 0);
- if (ireq->iochunk.map) {
- pcs_map_put(ireq->iochunk.map);
- ireq->iochunk.map = NULL;
+ if (ireq->iochunk.cmd == PCS_REQ_T_FIEMAP) {
+ pcs_api_iorequest_t * ar = ireq->completion_data.parent->apireq.req;
+ ireq->iochunk.size = len;
+ ar->size = ireq->iochunk.size;
+ } else {
+ struct pcs_int_request * sreq;
+
+ sreq = pcs_ireq_split(ireq, len, 0);
+ if (ireq->iochunk.map) {
+ pcs_map_put(ireq->iochunk.map);
+ ireq->iochunk.map = NULL;
+ }
+ ireq->iochunk.chunk = map_chunk_end(m);
+ ireq->iochunk.offset = 0;
+ pcs_cc_submit(ireq->dentry->cluster, ireq);
+ ireq = sreq;
}
- ireq->iochunk.chunk = map_chunk_end(m);
- ireq->iochunk.offset = 0;
- pcs_cc_submit(ireq->dentry->cluster, ireq);
- ireq = sreq;
}
}
@@ -2549,7 +2555,7 @@ static int commit_sync_info(struct pcs_int_request *req,
update_net_latency(csl, resp->rpc->peer_id, &h->sync, lat);
max_iolat = h->sync.ts_io;
- if (h->hdr.type != PCS_CS_READ_RESP) {
+ if (h->hdr.type != PCS_CS_READ_RESP && h->hdr.type != PCS_CS_FIEMAP_RESP) {
struct pcs_cs_sync_resp * srec;
lat = h->sync.ts_net;
for (srec = (struct pcs_cs_sync_resp*)(h + 1);
diff --git a/fs/fuse/kio/pcs/pcs_req.c b/fs/fuse/kio/pcs/pcs_req.c
index f1c364fe5f00..a05f1e43c94c 100644
--- a/fs/fuse/kio/pcs/pcs_req.c
+++ b/fs/fuse/kio/pcs/pcs_req.c
@@ -89,6 +89,12 @@ void ireq_handle_hole(struct pcs_int_request *ireq)
BUG_ON(ireq->type != PCS_IREQ_IOCHUNK);
BUG_ON(pcs_req_direction(ireq->iochunk.cmd));
+ if (ireq->iochunk.cmd == PCS_REQ_T_FIEMAP) {
+ ireq->completion_data.parent->apireq.aux = 0;
+ ireq_complete(ireq);
+ return;
+ }
+
len = ireq->iochunk.size;
offset = 0;
iov_iter_init_bad(&it);
diff --git a/fs/fuse/kio/pcs/pcs_req.h b/fs/fuse/kio/pcs/pcs_req.h
index bf603e0af414..fba74e9c4a56 100644
--- a/fs/fuse/kio/pcs/pcs_req.h
+++ b/fs/fuse/kio/pcs/pcs_req.h
@@ -150,6 +150,7 @@ struct pcs_int_request
struct {
pcs_api_iorequest_t * req; /* Client request */
unsigned int dio_offset; /* MBZ */
+ u64 aux;
void* h; /* API handle */
} apireq;
More information about the Devel
mailing list