[Virtio-fs] [PATCH-v2] virtiofs: FUSE_REMOVEMAPPING remove multiple entries in one call
Peng Tao
bergwolf at hyper.sh
Wed Jun 5 02:34:45 UTC 2019
On Wed, Jun 5, 2019 at 5:28 AM Vivek Goyal <vgoyal at redhat.com> wrote:
>
> On Mon, Jun 03, 2019 at 10:46:51AM +0800, Peng Tao wrote:
>
> [..]
> > +static 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, *n;
> > + int err, num = 0;
> > + LIST_HEAD(to_remove);
> > +
> > + pr_debug("fuse: __fuse_dax_free_mappings_range "
> > + "start=0x%llx, end=0x%llx\n", start, end);
> > + /* 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);
> > +
> > + while ((dmap = fuse_dax_interval_tree_iter_first(&fi->dmap_tree, start, end))) {
> > + fuse_dax_interval_tree_remove(dmap, &fi->dmap_tree);
> > + num++;
> > + list_add(&dmap->list, &to_remove);
>
> Hmm..... So normally dmap->list is used for putting an element in free list.
> Given this element is on busy list, it must not be on free list hence you
> are reusing dmap->list to put it temporarily on to_remove list.
Yes, when a dmap is in use, it must not be on the free list and thus
dmap->list is not used by anyone, so we can reuse it to link to the
to_remove list.
>
>
> > + }
> > +
> > + /* Nothing to remove */
> > + if (list_empty(&to_remove))
> > + return;
> > +
> > + WARN_ON(fi->nr_dmaps < num);
> > + fi->nr_dmaps -= num;
> > + /*
> > + * During umount/shutdown, fuse connection is dropped first
> > + * and later evict_inode() is called later. That means any
> > + * removemapping messages are going to fail. Send messages
> > + * only if connection is up. Otherwise fuse daemon is
> > + * responsible for cleaning up any leftover references and
> > + * mappings.
> > + */
> > + if (fc->connected) {
> > + err = fuse_do_removemappings(inode, num, &to_remove);
> > + if (err) {
> > + pr_warn("Failed to removemappings. start=0x%llx"
> > + " end=0x%llx\n", start, end);
> > + }
> > + }
> > + spin_lock(&fc->lock);
> > + list_for_each_entry_safe(dmap, n, &to_remove, list) {
> > + fuse_dax_do_free_mapping_locked(fc, dmap);
>
> What removes dmap from to_remove list. I think it gets added to free
> list and that overrides it? So an element is already part of to_remove
> list and then we are calling list_add_tail(&dmap->list, &fc->free_ranges)
> on it without removing it. That sounds wrong.
Good catch! I need list_del() here to keep to_remove list sane. Will fix it.
Thanks,
Tao
--
Into something rich and strange.
More information about the Virtio-fs
mailing list