* [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.