* [Virtio-fs] [PATCH-v3 0/2] fuse: remove dmap when truncating inode
@ 2019-05-24 5:33 Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 1/2] " Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries Peng Tao
0 siblings, 2 replies; 5+ messages in thread
From: Peng Tao @ 2019-05-24 5:33 UTC (permalink / raw)
To: virtio-fs; +Cc: Peng Tao
Hi Vivek,
The two patches try to remove dmap during truncation. virtiofs fuse
protocol is also modified to support removing multiple entries in
a single request. The host side virtiofsd patch will be sent separately.
Cheers,
Tao
v2->v3: change fuse_removemapping_in_header to hold fixed size field and
follow naming convension.
Peng Tao (2):
fuse: remove dmap when truncating inode
virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple
entries
fs/fuse/dir.c | 5 ++
fs/fuse/file.c | 134 ++++++++++++++++++++++++++++++++------
fs/fuse/fuse_i.h | 2 +
include/uapi/linux/fuse.h | 9 ++-
4 files changed, 129 insertions(+), 21 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Virtio-fs] [PATCH-v3 1/2] fuse: remove dmap when truncating inode
2019-05-24 5:33 [Virtio-fs] [PATCH-v3 0/2] fuse: remove dmap when truncating inode Peng Tao
@ 2019-05-24 5:33 ` Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries Peng Tao
1 sibling, 0 replies; 5+ messages in thread
From: Peng Tao @ 2019-05-24 5:33 UTC (permalink / raw)
To: virtio-fs; +Cc: Peng Tao
The obseleted dmap entries can be put back to global free list
immediately and we don't have to rely on reclaim code to free them.
Signed-off-by: Peng Tao <tao.peng@linux.alibaba.com>
---
fs/fuse/dir.c | 5 +++++
fs/fuse/file.c | 55 ++++++++++++++++++++++++++++++++++++++----------
fs/fuse/fuse_i.h | 2 ++
3 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 3f923fe7841a..233c3ed391f1 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1751,6 +1751,11 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
down_write(&fi->i_mmap_sem);
truncate_pagecache(inode, outarg.attr.size);
invalidate_inode_pages2(inode->i_mapping);
+ // Free dmap beyond i_size
+ if (IS_DAX(inode) && oldsize > outarg.attr.size)
+ fuse_dax_free_mappings_range(fc, inode,
+ outarg.attr.size, -1);
+
up_write(&fi->i_mmap_sem);
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 51faed351c7c..6c970d19e926 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3752,7 +3752,6 @@ int fuse_dax_reclaim_dmap_locked(struct fuse_conn *fc, struct inode *inode,
return ret;
}
- /* Remove dax mapping from inode interval tree now */
fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
fi->nr_dmaps--;
return 0;
@@ -3831,6 +3830,49 @@ static struct fuse_dax_mapping *alloc_dax_mapping_reclaim(struct fuse_conn *fc,
}
}
+/* Cleanup dmap entry and add back to free list */
+static void fuse_dax_do_free_mapping_locked(struct fuse_conn *fc, struct fuse_dax_mapping *dmap)
+{
+ pr_debug("fuse: freed memory range start=0x%llx end=0x%llx "
+ "window_offset=0x%llx length=0x%llx\n", dmap->start,
+ dmap->end, dmap->window_offset, dmap->length);
+ spin_lock(&fc->lock);
+ __dmap_remove_busy_list(fc, dmap);
+ dmap->inode = NULL;
+ dmap->start = dmap->end = 0;
+ __free_dax_mapping(fc, dmap);
+ spin_unlock(&fc->lock);
+}
+
+/*
+ * Free inode dmap entries whose range falls entirely inside [start, end].
+ * Called with inode->i_rwsem and fuse_inode->i_mmap_sem held.
+ */
+void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, loff_t start, loff_t end)
+{
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_dax_mapping *dmap;
+
+ WARN_ON(!inode_is_locked(inode));
+ WARN_ON(!rwsem_is_locked(&fi->i_mmap_sem));
+
+ /* interval tree search matches intersecting entries.
+ * Adjust the range to avoid dropping partial valid entries. */
+ start = ALIGN(start, FUSE_DAX_MEM_RANGE_SZ);
+ end = ALIGN_DOWN(end, FUSE_DAX_MEM_RANGE_SZ);
+
+ pr_debug("fuse: fuse_dax_free_mappings_range start=0x%llx, end=0x%llx\n", start, end);
+ /* Lock ordering follows fuse_dax_free_one_mapping() */
+ down_write(&fi->i_dmap_sem);
+ while ((dmap = fuse_dax_interval_tree_iter_first(&fi->dmap_tree, start, end))) {
+ fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
+ fi->nr_dmaps--;
+ fuse_dax_do_free_mapping_locked(fc, dmap);
+ fuse_removemapping_one(inode, dmap);
+ }
+ up_write(&fi->i_dmap_sem);
+}
+
int fuse_dax_free_one_mapping_locked(struct fuse_conn *fc, struct inode *inode,
u64 dmap_start)
{
@@ -3852,17 +3894,8 @@ int fuse_dax_free_one_mapping_locked(struct fuse_conn *fc, struct inode *inode,
if (ret < 0)
return ret;
- /* Cleanup dmap entry and add back to free list */
- spin_lock(&fc->lock);
- __dmap_remove_busy_list(fc, dmap);
- dmap->inode = NULL;
- dmap->start = dmap->end = 0;
- __free_dax_mapping(fc, dmap);
- spin_unlock(&fc->lock);
+ fuse_dax_do_free_mapping_locked(fc, dmap);
- pr_debug("fuse: freed memory range window_offset=0x%llx,"
- " length=0x%llx\n", dmap->window_offset,
- dmap->length);
return ret;
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 1149281ab1e8..e273f1209f5b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1189,5 +1189,7 @@ unsigned fuse_len_args(unsigned numargs, struct fuse_arg *args);
u64 fuse_get_unique(struct fuse_iqueue *fiq);
void fuse_dax_free_mem_worker(struct work_struct *work);
void fuse_removemapping(struct inode *inode);
+void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode,
+ loff_t start, loff_t end);
#endif /* _FS_FUSE_I_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries
2019-05-24 5:33 [Virtio-fs] [PATCH-v3 0/2] fuse: remove dmap when truncating inode Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 1/2] " Peng Tao
@ 2019-05-24 5:33 ` Peng Tao
2019-05-28 21:38 ` Vivek Goyal
1 sibling, 1 reply; 5+ messages in thread
From: Peng Tao @ 2019-05-24 5:33 UTC (permalink / raw)
To: virtio-fs; +Cc: Peng Tao
Change FUSE_REMOVEMAPPING wire protocol so that we can remove
multiple mappings in one call.
Signed-off-by: Peng Tao <tao.peng@linux.alibaba.com>
---
fs/fuse/file.c | 85 +++++++++++++++++++++++++++++++++------
include/uapi/linux/fuse.h | 9 ++++-
2 files changed, 81 insertions(+), 13 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6c970d19e926..03c81baa8989 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -320,25 +320,80 @@ static int fuse_setup_one_mapping(struct inode *inode,
return 0;
}
-static int fuse_removemapping_one(struct inode *inode,
- struct fuse_dax_mapping *dmap)
+static int fuse_send_removemapping_request(struct inode *inode,
+ struct fuse_removemapping_in_header *header,
+ struct fuse_removemapping_in *inargp)
{
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_removemapping_in inarg;
FUSE_ARGS(args);
- memset(&inarg, 0, sizeof(inarg));
- inarg.moffset = dmap->window_offset;
- inarg.len = dmap->length;
args.in.h.opcode = FUSE_REMOVEMAPPING;
args.in.h.nodeid = fi->nodeid;
- args.in.numargs = 1;
- args.in.args[0].size = sizeof(inarg);
- args.in.args[0].value = &inarg;
+ args.in.numargs = 2;
+ args.in.args[0].size = sizeof(*header);
+ args.in.args[0].value = header;
+ args.in.args[1].size = header->count * sizeof(*inargp);
+ args.in.args[1].value = inargp;
return fuse_simple_request(fc, &args);
}
+static int fuse_removemappings(struct inode *inode, unsigned num,
+ struct list_head *to_remove)
+{
+ struct fuse_removemapping_in *inargp, *ptr;
+ struct fuse_removemapping_in_header header;
+ struct fuse_dax_mapping *dmap;
+ int ret, i = 0;
+
+ if (num <= FUSE_REMOVEMAPPING_MAX_ENTRY) {
+ inargp = kmalloc_array(num, sizeof(*inargp), GFP_NOIO);
+ } else {
+ inargp = kmalloc_array(FUSE_REMOVEMAPPING_MAX_ENTRY,
+ sizeof(*inargp), GFP_NOIO);
+ }
+ if (inargp == NULL)
+ return -ENOMEM;
+
+ ptr = inargp;
+ list_for_each_entry(dmap, to_remove, list) {
+ ptr->moffset = dmap->window_offset;
+ ptr->len = dmap->length;
+ ptr++;
+ i++;
+ num--;
+ if (i >= FUSE_REMOVEMAPPING_MAX_ENTRY || num == 0) {
+ memset(&header, 0, sizeof(header));
+ header.count = i;
+ ret = fuse_send_removemapping_request(inode, &header, inargp);
+ if (ret)
+ goto out;
+ ptr = inargp;
+ i = 0;
+ }
+ }
+
+out:
+ kfree(inargp);
+ return ret;
+}
+
+static int fuse_removemapping_one(struct inode *inode,
+ struct fuse_dax_mapping *dmap)
+{
+ struct fuse_removemapping_in inarg;
+ struct fuse_removemapping_in_header header;
+
+ memset(&header, 0, sizeof(header));
+ /* TODO: fill in header.fh when available */
+ header.count = 1;
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.moffset = dmap->window_offset;
+ inarg.len = dmap->length;
+
+ return fuse_send_removemapping_request(inode, &header, &inarg);
+}
+
/*
* It is called from evict_inode() and by that time inode is going away. So
* this function does not take any locks like fi->i_dmap_sem for traversing
@@ -3851,7 +3906,9 @@ static void fuse_dax_do_free_mapping_locked(struct fuse_conn *fc, struct fuse_da
void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, loff_t start, loff_t end)
{
struct fuse_inode *fi = get_fuse_inode(inode);
- struct fuse_dax_mapping *dmap;
+ struct fuse_dax_mapping *dmap, *n;
+ int num = 0;
+ LIST_HEAD(to_remove);
WARN_ON(!inode_is_locked(inode));
WARN_ON(!rwsem_is_locked(&fi->i_mmap_sem));
@@ -3866,9 +3923,13 @@ void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, lof
down_write(&fi->i_dmap_sem);
while ((dmap = fuse_dax_interval_tree_iter_first(&fi->dmap_tree, start, end))) {
fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
- fi->nr_dmaps--;
+ num++;
+ list_add(&dmap->list, &to_remove);
+ }
+ fi->nr_dmaps -= num;
+ fuse_removemappings(inode, num, &to_remove);
+ list_for_each_entry_safe(dmap, n, &to_remove, list) {
fuse_dax_do_free_mapping_locked(fc, dmap);
- fuse_removemapping_one(inode, dmap);
}
up_write(&fi->i_dmap_sem);
}
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index dbc5013ad747..69ddedca4177 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -817,13 +817,20 @@ struct fuse_setupmapping_out {
uint64_t len[FUSE_SETUPMAPPING_ENTRIES];
};
-struct fuse_removemapping_in {
+struct fuse_removemapping_in_header {
/* An already open handle */
uint64_t fh;
+ /* number of fuse_removemapping_in follows */
+ uint32_t count;
+};
+
+struct fuse_removemapping_in {
/* Offset into the dax window start the unmapping */
uint64_t moffset;
/* Length of mapping required */
uint64_t len;
};
+#define FUSE_REMOVEMAPPING_MAX_ENTRY \
+ (PAGE_SIZE / sizeof(struct fuse_removemapping_in))
#endif /* _LINUX_FUSE_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries Peng Tao
@ 2019-05-28 21:38 ` Vivek Goyal
2019-05-29 2:09 ` Tao Peng
0 siblings, 1 reply; 5+ messages in thread
From: Vivek Goyal @ 2019-05-28 21:38 UTC (permalink / raw)
To: Peng Tao; +Cc: virtio-fs
On Fri, May 24, 2019 at 01:33:24PM +0800, Peng Tao wrote:
> Change FUSE_REMOVEMAPPING wire protocol so that we can remove
> multiple mappings in one call.
>
> Signed-off-by: Peng Tao <tao.peng@linux.alibaba.com>
Hi Tao,
How about posting a patch for enabling multiple entries in
fuse_removemapping in one patch.
Lets first merge that patch in kernel and virtiofsd. And post patches
to remove mappings on truncate later? That's an optimization and
can wait a bit.
Thanks
Vivek
> ---
> fs/fuse/file.c | 85 +++++++++++++++++++++++++++++++++------
> include/uapi/linux/fuse.h | 9 ++++-
> 2 files changed, 81 insertions(+), 13 deletions(-)
>
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 6c970d19e926..03c81baa8989 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -320,25 +320,80 @@ static int fuse_setup_one_mapping(struct inode *inode,
> return 0;
> }
>
> -static int fuse_removemapping_one(struct inode *inode,
> - struct fuse_dax_mapping *dmap)
> +static int fuse_send_removemapping_request(struct inode *inode,
> + struct fuse_removemapping_in_header *header,
> + struct fuse_removemapping_in *inargp)
> {
> struct fuse_inode *fi = get_fuse_inode(inode);
> struct fuse_conn *fc = get_fuse_conn(inode);
> - struct fuse_removemapping_in inarg;
> FUSE_ARGS(args);
>
> - memset(&inarg, 0, sizeof(inarg));
> - inarg.moffset = dmap->window_offset;
> - inarg.len = dmap->length;
> args.in.h.opcode = FUSE_REMOVEMAPPING;
> args.in.h.nodeid = fi->nodeid;
> - args.in.numargs = 1;
> - args.in.args[0].size = sizeof(inarg);
> - args.in.args[0].value = &inarg;
> + args.in.numargs = 2;
> + args.in.args[0].size = sizeof(*header);
> + args.in.args[0].value = header;
> + args.in.args[1].size = header->count * sizeof(*inargp);
> + args.in.args[1].value = inargp;
> return fuse_simple_request(fc, &args);
> }
>
> +static int fuse_removemappings(struct inode *inode, unsigned num,
> + struct list_head *to_remove)
> +{
> + struct fuse_removemapping_in *inargp, *ptr;
> + struct fuse_removemapping_in_header header;
> + struct fuse_dax_mapping *dmap;
> + int ret, i = 0;
> +
> + if (num <= FUSE_REMOVEMAPPING_MAX_ENTRY) {
> + inargp = kmalloc_array(num, sizeof(*inargp), GFP_NOIO);
> + } else {
> + inargp = kmalloc_array(FUSE_REMOVEMAPPING_MAX_ENTRY,
> + sizeof(*inargp), GFP_NOIO);
> + }
> + if (inargp == NULL)
> + return -ENOMEM;
> +
> + ptr = inargp;
> + list_for_each_entry(dmap, to_remove, list) {
> + ptr->moffset = dmap->window_offset;
> + ptr->len = dmap->length;
> + ptr++;
> + i++;
> + num--;
> + if (i >= FUSE_REMOVEMAPPING_MAX_ENTRY || num == 0) {
> + memset(&header, 0, sizeof(header));
> + header.count = i;
> + ret = fuse_send_removemapping_request(inode, &header, inargp);
> + if (ret)
> + goto out;
> + ptr = inargp;
> + i = 0;
> + }
> + }
> +
> +out:
> + kfree(inargp);
> + return ret;
> +}
> +
> +static int fuse_removemapping_one(struct inode *inode,
> + struct fuse_dax_mapping *dmap)
> +{
> + struct fuse_removemapping_in inarg;
> + struct fuse_removemapping_in_header header;
> +
> + memset(&header, 0, sizeof(header));
> + /* TODO: fill in header.fh when available */
> + header.count = 1;
> + memset(&inarg, 0, sizeof(inarg));
> + inarg.moffset = dmap->window_offset;
> + inarg.len = dmap->length;
> +
> + return fuse_send_removemapping_request(inode, &header, &inarg);
> +}
> +
> /*
> * It is called from evict_inode() and by that time inode is going away. So
> * this function does not take any locks like fi->i_dmap_sem for traversing
> @@ -3851,7 +3906,9 @@ static void fuse_dax_do_free_mapping_locked(struct fuse_conn *fc, struct fuse_da
> void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, loff_t start, loff_t end)
> {
> struct fuse_inode *fi = get_fuse_inode(inode);
> - struct fuse_dax_mapping *dmap;
> + struct fuse_dax_mapping *dmap, *n;
> + int num = 0;
> + LIST_HEAD(to_remove);
>
> WARN_ON(!inode_is_locked(inode));
> WARN_ON(!rwsem_is_locked(&fi->i_mmap_sem));
> @@ -3866,9 +3923,13 @@ void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, lof
> down_write(&fi->i_dmap_sem);
> while ((dmap = fuse_dax_interval_tree_iter_first(&fi->dmap_tree, start, end))) {
> fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
> - fi->nr_dmaps--;
> + num++;
> + list_add(&dmap->list, &to_remove);
> + }
> + fi->nr_dmaps -= num;
> + fuse_removemappings(inode, num, &to_remove);
> + list_for_each_entry_safe(dmap, n, &to_remove, list) {
> fuse_dax_do_free_mapping_locked(fc, dmap);
> - fuse_removemapping_one(inode, dmap);
> }
> up_write(&fi->i_dmap_sem);
> }
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index dbc5013ad747..69ddedca4177 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.h
> @@ -817,13 +817,20 @@ struct fuse_setupmapping_out {
> uint64_t len[FUSE_SETUPMAPPING_ENTRIES];
> };
>
> -struct fuse_removemapping_in {
> +struct fuse_removemapping_in_header {
> /* An already open handle */
> uint64_t fh;
> + /* number of fuse_removemapping_in follows */
> + uint32_t count;
> +};
> +
> +struct fuse_removemapping_in {
> /* Offset into the dax window start the unmapping */
> uint64_t moffset;
> /* Length of mapping required */
> uint64_t len;
> };
> +#define FUSE_REMOVEMAPPING_MAX_ENTRY \
> + (PAGE_SIZE / sizeof(struct fuse_removemapping_in))
>
> #endif /* _LINUX_FUSE_H */
> --
> 2.17.1
>
> _______________________________________________
> Virtio-fs mailing list
> Virtio-fs@redhat.com
> https://www.redhat.com/mailman/listinfo/virtio-fs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries
2019-05-28 21:38 ` Vivek Goyal
@ 2019-05-29 2:09 ` Tao Peng
0 siblings, 0 replies; 5+ messages in thread
From: Tao Peng @ 2019-05-29 2:09 UTC (permalink / raw)
To: Vivek Goyal; +Cc: virtio-fs, Peng Tao
On Wed, May 29, 2019 at 5:38 AM Vivek Goyal <vgoyal@redhat.com> wrote:
>
> On Fri, May 24, 2019 at 01:33:24PM +0800, Peng Tao wrote:
> > Change FUSE_REMOVEMAPPING wire protocol so that we can remove
> > multiple mappings in one call.
> >
> > Signed-off-by: Peng Tao <tao.peng@linux.alibaba.com>
>
> Hi Tao,
>
> How about posting a patch for enabling multiple entries in
> fuse_removemapping in one patch.
>
> Lets first merge that patch in kernel and virtiofsd. And post patches
> to remove mappings on truncate later? That's an optimization and
> can wait a bit.
Sure, no problem!
Cheers,
Tao
>
> Thanks
> Vivek
>
> > ---
> > fs/fuse/file.c | 85 +++++++++++++++++++++++++++++++++------
> > include/uapi/linux/fuse.h | 9 ++++-
> > 2 files changed, 81 insertions(+), 13 deletions(-)
> >
> > diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> > index 6c970d19e926..03c81baa8989 100644
> > --- a/fs/fuse/file.c
> > +++ b/fs/fuse/file.c
> > @@ -320,25 +320,80 @@ static int fuse_setup_one_mapping(struct inode *inode,
> > return 0;
> > }
> >
> > -static int fuse_removemapping_one(struct inode *inode,
> > - struct fuse_dax_mapping *dmap)
> > +static int fuse_send_removemapping_request(struct inode *inode,
> > + struct fuse_removemapping_in_header *header,
> > + struct fuse_removemapping_in *inargp)
> > {
> > struct fuse_inode *fi = get_fuse_inode(inode);
> > struct fuse_conn *fc = get_fuse_conn(inode);
> > - struct fuse_removemapping_in inarg;
> > FUSE_ARGS(args);
> >
> > - memset(&inarg, 0, sizeof(inarg));
> > - inarg.moffset = dmap->window_offset;
> > - inarg.len = dmap->length;
> > args.in.h.opcode = FUSE_REMOVEMAPPING;
> > args.in.h.nodeid = fi->nodeid;
> > - args.in.numargs = 1;
> > - args.in.args[0].size = sizeof(inarg);
> > - args.in.args[0].value = &inarg;
> > + args.in.numargs = 2;
> > + args.in.args[0].size = sizeof(*header);
> > + args.in.args[0].value = header;
> > + args.in.args[1].size = header->count * sizeof(*inargp);
> > + args.in.args[1].value = inargp;
> > return fuse_simple_request(fc, &args);
> > }
> >
> > +static int fuse_removemappings(struct inode *inode, unsigned num,
> > + struct list_head *to_remove)
> > +{
> > + struct fuse_removemapping_in *inargp, *ptr;
> > + struct fuse_removemapping_in_header header;
> > + struct fuse_dax_mapping *dmap;
> > + int ret, i = 0;
> > +
> > + if (num <= FUSE_REMOVEMAPPING_MAX_ENTRY) {
> > + inargp = kmalloc_array(num, sizeof(*inargp), GFP_NOIO);
> > + } else {
> > + inargp = kmalloc_array(FUSE_REMOVEMAPPING_MAX_ENTRY,
> > + sizeof(*inargp), GFP_NOIO);
> > + }
> > + if (inargp == NULL)
> > + return -ENOMEM;
> > +
> > + ptr = inargp;
> > + list_for_each_entry(dmap, to_remove, list) {
> > + ptr->moffset = dmap->window_offset;
> > + ptr->len = dmap->length;
> > + ptr++;
> > + i++;
> > + num--;
> > + if (i >= FUSE_REMOVEMAPPING_MAX_ENTRY || num == 0) {
> > + memset(&header, 0, sizeof(header));
> > + header.count = i;
> > + ret = fuse_send_removemapping_request(inode, &header, inargp);
> > + if (ret)
> > + goto out;
> > + ptr = inargp;
> > + i = 0;
> > + }
> > + }
> > +
> > +out:
> > + kfree(inargp);
> > + return ret;
> > +}
> > +
> > +static int fuse_removemapping_one(struct inode *inode,
> > + struct fuse_dax_mapping *dmap)
> > +{
> > + struct fuse_removemapping_in inarg;
> > + struct fuse_removemapping_in_header header;
> > +
> > + memset(&header, 0, sizeof(header));
> > + /* TODO: fill in header.fh when available */
> > + header.count = 1;
> > + memset(&inarg, 0, sizeof(inarg));
> > + inarg.moffset = dmap->window_offset;
> > + inarg.len = dmap->length;
> > +
> > + return fuse_send_removemapping_request(inode, &header, &inarg);
> > +}
> > +
> > /*
> > * It is called from evict_inode() and by that time inode is going away. So
> > * this function does not take any locks like fi->i_dmap_sem for traversing
> > @@ -3851,7 +3906,9 @@ static void fuse_dax_do_free_mapping_locked(struct fuse_conn *fc, struct fuse_da
> > void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, loff_t start, loff_t end)
> > {
> > struct fuse_inode *fi = get_fuse_inode(inode);
> > - struct fuse_dax_mapping *dmap;
> > + struct fuse_dax_mapping *dmap, *n;
> > + int num = 0;
> > + LIST_HEAD(to_remove);
> >
> > WARN_ON(!inode_is_locked(inode));
> > WARN_ON(!rwsem_is_locked(&fi->i_mmap_sem));
> > @@ -3866,9 +3923,13 @@ void fuse_dax_free_mappings_range(struct fuse_conn *fc, struct inode *inode, lof
> > down_write(&fi->i_dmap_sem);
> > while ((dmap = fuse_dax_interval_tree_iter_first(&fi->dmap_tree, start, end))) {
> > fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
> > - fi->nr_dmaps--;
> > + num++;
> > + list_add(&dmap->list, &to_remove);
> > + }
> > + fi->nr_dmaps -= num;
> > + fuse_removemappings(inode, num, &to_remove);
> > + list_for_each_entry_safe(dmap, n, &to_remove, list) {
> > fuse_dax_do_free_mapping_locked(fc, dmap);
> > - fuse_removemapping_one(inode, dmap);
> > }
> > up_write(&fi->i_dmap_sem);
> > }
> > diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> > index dbc5013ad747..69ddedca4177 100644
> > --- a/include/uapi/linux/fuse.h
> > +++ b/include/uapi/linux/fuse.h
> > @@ -817,13 +817,20 @@ struct fuse_setupmapping_out {
> > uint64_t len[FUSE_SETUPMAPPING_ENTRIES];
> > };
> >
> > -struct fuse_removemapping_in {
> > +struct fuse_removemapping_in_header {
> > /* An already open handle */
> > uint64_t fh;
> > + /* number of fuse_removemapping_in follows */
> > + uint32_t count;
> > +};
> > +
> > +struct fuse_removemapping_in {
> > /* Offset into the dax window start the unmapping */
> > uint64_t moffset;
> > /* Length of mapping required */
> > uint64_t len;
> > };
> > +#define FUSE_REMOVEMAPPING_MAX_ENTRY \
> > + (PAGE_SIZE / sizeof(struct fuse_removemapping_in))
> >
> > #endif /* _LINUX_FUSE_H */
> > --
> > 2.17.1
> >
> > _______________________________________________
> > Virtio-fs mailing list
> > Virtio-fs@redhat.com
> > https://www.redhat.com/mailman/listinfo/virtio-fs
>
> _______________________________________________
> Virtio-fs mailing list
> Virtio-fs@redhat.com
> https://www.redhat.com/mailman/listinfo/virtio-fs
--
bergwolf@hyper.sh
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-05-29 2:09 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-24 5:33 [Virtio-fs] [PATCH-v3 0/2] fuse: remove dmap when truncating inode Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 1/2] " Peng Tao
2019-05-24 5:33 ` [Virtio-fs] [PATCH-v3 2/2] virtiofs: FUSE_REMOVEMAPPING support multiple removing multiple entries Peng Tao
2019-05-28 21:38 ` Vivek Goyal
2019-05-29 2:09 ` Tao Peng
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.