Re: [PATCH v14 24/31] ovl: Set redirect on upper inode when it is linked

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

 



On Thu, Apr 26, 2018 at 12:10 PM, Vivek Goyal <vgoyal@xxxxxxxxxx> wrote:
> When we create a hardlink to a metacopy upper file, first the redirect
> on that inode. Path based lookup will not work with newly created link
> and redirect will solve that issue.
>
> Also use absolute redirect as two hardlinks could be in different directores
> and relative redirect will not work.
>
> I have not put any additional locking around setting redirects while
> introducing redirects for non-dir files. For now it feels like existing
> locking is sufficient. If that's not the case, we will have add more
> locking. Following is my rationale about why do I think current locking
> seems ok.
>
> Basic problem for non-dir files is that more than on dentry could be
> pointing to same inode and in theory only relying on dentry based locks
> (d->d_lock) did not seem sufficient.
>
> We set redirect upon rename and upon link creation. In both the paths
> for non-dir file, VFS locks both source and target inodes (->i_rwsem).
> That means vfs rename and link operations on same source and target
> can't he happening in parallel (Even if there are multiple dentries
> pointing to same inode). So that probably means that at a time on an inode,
> only one call of ovl_set_redirect() could be working and we don't need
> additional locking in ovl_set_redirect().
>
> ovl_inode->redirect is initialized only when inode is created new. That
> means it should not race with any other path and setting ovl_inode->redirect
> should be fine.
>
> Reading of ovl_inode->redirect happens in ovl_get_redirect() path. And this
> called only in ovl_set_redirect(). And ovl_set_redirect() already seemed
> to be protected using ->i_rwsem. That means ovl_set_redirect() and
> ovl_get_redirect() on source/target inode should not make progress in
> parallel and is mutually exclusive. Hence no additional locking required.
>
> Now, only case where ovl_set_redirect() and ovl_get_redirect() could race
> seems to be case of absolute redirects where ovl_get_redirect() has to
> travel up the tree. In that case we already take d->d_lock and that should
> be sufficient as directories will not have multiple dentries pointing to
> same inode.
>
> So given VFS locking and current usage of redirect, current locking around
> redirect seems to be ok for non-dir as well. Once we have the logic to
> remove redirect when metacopy file gets copied up, then we probably will
> need additional locking.
>
> Signed-off-by: Vivek Goyal <vgoyal@xxxxxxxxxx>

Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx>

> ---
>  fs/overlayfs/dir.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index 1acea6887b05..546ad7d34160 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -24,6 +24,8 @@ module_param_named(redirect_max, ovl_redirect_max, ushort, 0644);
>  MODULE_PARM_DESC(ovl_redirect_max,
>                  "Maximum length of absolute redirect xattr value");
>
> +static int ovl_set_redirect(struct dentry *dentry, bool samedir);
> +
>  int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
>  {
>         int err;
> @@ -468,6 +470,9 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
>         const struct cred *old_cred;
>         struct cred *override_cred;
>         struct dentry *parent = dentry->d_parent;
> +       struct dentry *hardlink_upper;
> +
> +       hardlink_upper = hardlink ? ovl_dentry_upper(hardlink) : NULL;
>
>         err = ovl_copy_up(parent);
>         if (err)
> @@ -502,12 +507,19 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
>                 put_cred(override_creds(override_cred));
>                 put_cred(override_cred);
>
> +               if (hardlink && ovl_is_metacopy_dentry(hardlink)) {
> +                       err = ovl_set_redirect(hardlink, false);
> +                       if (err)
> +                               goto out_revert_creds;
> +               }
> +
> +
>                 if (!ovl_dentry_is_whiteout(dentry))
>                         err = ovl_create_upper(dentry, inode, attr,
> -                                               hardlink);
> +                                               hardlink_upper);
>                 else
>                         err = ovl_create_over_whiteout(dentry, inode, attr,
> -                                                       hardlink);
> +                                                       hardlink_upper);
>                 ovl_copytimes_with_parent(dentry);
>         }
>  out_revert_creds:
> @@ -603,8 +615,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
>         inode = d_inode(old);
>         ihold(inode);
>
> -       err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old),
> -                                ovl_type_origin(old));
> +       err = ovl_create_or_link(new, inode, NULL, old, ovl_type_origin(old));
>         if (err)
>                 iput(inode);
>
> --
> 2.13.6
>
--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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