Messages in this thread Patch in this message | | | From | Alexander Morozov <> | Subject | [PATCH 2/2] fs/overlay: use same inodes for hardlinks | Date | Fri, 9 Oct 2015 12:34:57 -0700 |
| |
Fix problem with accessing hardlink to unix-socket. unix_find_other function from net/unix/af_unix.c uses d_backing_inode helper which in current implementation doesn't return any "backing" inode, but just dentry->d_inode, so, there from kern_path we have path with dentry from overlayfs and not underlying file system. Further in code in unix_find_socket_byinode we looking for unix-socket by inode, but due overlayfs implementation that inode for hardlink will be different from original inode of unix-socket. Now ovl_link doesn't create new inode, but uses old->d_inode for instantiating new dentry. Not use inc_nlink, because nlink seems to be correctly propagated from underlying fs where it need.
Signed-off-by: Alexander Morozov <lk4d4@docker.com> --- fs/overlayfs/dir.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 487a157..a55c89b 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -164,8 +164,14 @@ static void ovl_dentry_update_instantiate(struct dentry *dentry, { ovl_dentry_version_inc(dentry->d_parent); ovl_dentry_update(dentry, newdentry); - ovl_copyattr(newdentry->d_inode, inode); - d_instantiate(dentry, inode); + /* + * inode == NULL only in case of hardlink + * for hardlink dentry will be instantiated in ovl_link + */ + if (inode) { + ovl_copyattr(newdentry->d_inode, inode); + d_instantiate(dentry, inode); + } } static int ovl_create_upper(struct dentry *dentry, struct inode *inode, @@ -390,16 +396,19 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, const char *link, struct dentry *hardlink) { int err; - struct inode *inode; + struct inode *inode = NULL; struct kstat stat = { .mode = mode, .rdev = rdev, }; err = -ENOMEM; - inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata); - if (!inode) - goto out; + /* We don't need inode for hardlink */ + if (!hardlink) { + inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata); + if (!inode) + goto out; + } err = ovl_copy_up(dentry->d_parent); if (err) @@ -498,6 +507,10 @@ static int ovl_link(struct dentry *old, struct inode *newdir, upper = ovl_dentry_upper(old); err = ovl_create_or_link(new, upper->d_inode->i_mode, 0, NULL, upper); + if (!err) { + ihold(old->d_inode); + d_instantiate(new, old->d_inode); + } out_drop_write: ovl_drop_write(old); -- 2.6.1
| |