Re: [PATCH v3] ovl: whiteout inode sharing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 15, 2020 at 4:03 AM Chengguang Xu <cgxu519@xxxxxxxxxxxx> wrote:
>
>  ---- 在 星期二, 2020-04-14 21:44:39 Amir Goldstein <amir73il@xxxxxxxxx> 撰写 ----
>  > On Tue, Apr 14, 2020 at 12:53 PM Chengguang Xu <cgxu519@xxxxxxxxxxxx> wrote:
>  > >
>  > > Sharing inode with different whiteout files for saving
>  > > inode and speeding up deleting operation.
>  > >
>  > > Signed-off-by: Chengguang Xu <cgxu519@xxxxxxxxxxxx>
>  > > ---
>  > > v1->v2:
>  > > - Address Amir's comments in v1
>  > >
>  > > v2->v3:
>  > > - Address Amir's comments in v2
>  > > - Rebase on Amir's "Overlayfs use index dir as work dir" patch set
>  > > - Keep at most one whiteout tmpfile in work dir
>  > >
>  > >  fs/overlayfs/dir.c       | 35 ++++++++++++++++++++++++++++-------
>  > >  fs/overlayfs/overlayfs.h |  9 +++++++--
>  > >  fs/overlayfs/ovl_entry.h |  4 ++++
>  > >  fs/overlayfs/readdir.c   |  3 ++-
>  > >  fs/overlayfs/super.c     |  9 +++++++++
>  > >  fs/overlayfs/util.c      |  3 ++-
>  > >  6 files changed, 52 insertions(+), 11 deletions(-)
>  > >
>  > > diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
>  > > index 279009dee366..dbe5e54dcb16 100644
>  > > --- a/fs/overlayfs/dir.c
>  > > +++ b/fs/overlayfs/dir.c
>  > > @@ -62,35 +62,55 @@ struct dentry *ovl_lookup_temp(struct dentry *workdir)
>  > >  }
>  > >
>  > >  /* caller holds i_mutex on workdir */
>  > > -static struct dentry *ovl_whiteout(struct dentry *workdir)
>  > > +static struct dentry *ovl_whiteout(struct ovl_fs *ofs, struct dentry *workdir)
>  > >  {
>  > >         int err;
>  > > +       bool retried = false;
>  > > +       bool should_link = (ofs->whiteout_link_max > 1);
>  > >         struct dentry *whiteout;
>  > >         struct inode *wdir = workdir->d_inode;
>  > >
>  > > +retry:
>  > >         whiteout = ovl_lookup_temp(workdir);
>  > >         if (IS_ERR(whiteout))
>  > >                 return whiteout;
>  > >
>  > > +       if (should_link && ofs->whiteout) {
>  >
>  > What happens with ofs->whiteout_link_max == 2 is that half of the
>  > times, whiteout gets linked and then unlinked.
>  > That is not needed.
>  > I think code would look better like this:
>  >
>  >           if (ovl_whiteout_linkable(ofs)) {
>  >                   err = ovl_do_link(ofs->whiteout, wdir, whiteout);
>  > ...
>  >           } else if (ofs->whiteout) {
>  >                   ovl_cleanup(wdir, ofs->whiteout);
>  > ....
>  >
>  > With:
>  >
>  > static inline bool ovl_whiteout_linkable(struct ovl_fs *ofs)
>  > {
>  >        return ofs->whiteout &&
>  >                  ofs->whiteout->d_inode->i_nlink < ofs->whiteout_link_max;
>  > }
>  >
>
> tmpfile has occupied one link, so the maximum link count of whiteout inode
> in your code will be ofs->whiteout_link_max - 1, right?
>

Right, but I wrote wrong pseudo code to use this helper.
The intention is that ovl_whiteout_linkable(ofs) means there is a tmp whiteout
and it may be linked to a new tmp whiteout.
The only reason to cleanup tmp whiteout is if link has unexpectedly failed and
in this case I think we should disable whiteout sharing.

Let me try again:

+       err = -EMLINK;
+       if (ovl_whiteout_linkable(ofs)) {
+               err = ovl_do_link(ofs->whiteout, wdir, whiteout);
+               if (!err)
+                       return whiteout;
+        }
+        if (err && ofs->whiteout) {
+               pr_warn("failed to link whiteout - disabling whiteout
sharing (nlink=%u, err = %i)\n",
+                             ofs->whiteout->d_inode->i_nlink, err);
+               ofs->whiteout_link_max = 0;
+               should_link = false;
+               ovl_cleanup(wdir, ofs->whiteout);
+               dput(ofs->whiteout);
+               ofs->whiteout = NULL;
+       }
+
         err = ovl_do_whiteout(wdir, whiteout);

Is that better?

Thanks,
Amir.




[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux