Re: two questiones about overlayfs

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

 



On Tue, Aug 08, 2017 at 07:01:30AM +0200, Amir Goldstein wrote:
> On Mon, Aug 7, 2017 at 9:57 AM, zhangyi (F) <yi.zhang@xxxxxxxxxx> wrote:
> > Hi,all:
> > I found two problemes about overlayfs, please let me know what you think:
> >
> > 1. Cannot update upper dir's access time.
> > Reproduce:
> > # mkdir lower upper worker merger
> > # mkdir upper/dir
> > # mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=worker overlayfs merger
> > # ls mrger/dir
> > # stat mrger/dir
> >   Access: 2017-08-07 11:03:56.364771584 -0400
> >   Modify: 2017-08-07 11:01:52.319771584 -0400
> >   Change: 2017-08-07 11:01:52.319771584 -0400
> > # touch mrger/dir/aa
> > # stat mrger/dir
> >   Access: 2017-08-07 11:03:56.364771584 -0400
> >   Modify: 2017-08-07 11:05:33.969771584 -0400
> >   Change: 2017-08-07 11:05:33.969771584 -0400
> > # ls mrger/dir
> > # stat mrger/dir
> >   Access: 2017-08-07 11:03:56.364771584 -0400
> >   Modify: 2017-08-07 11:05:33.969771584 -0400
> >   Change: 2017-08-07 11:05:33.969771584 -0400
> >
> > I find the reason of this problem is in update_ovl_inode_times():
> > (598e3c8f7 "vfs: update ovl inode before relatime check")
> >
> > static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
> >                                bool rcu)
> > {
> >         if (!rcu) {
> >                 struct inode *realinode = d_real_inode(dentry);
> >
> >         *d_real_inode() cannot get dir's real inode, so i_mtime always equal to i_ctime*
> >         *an not updated*
> >
> 
> Technically, I think this could be changed to check
> if unlikely(dentry->d_flags & DCACHE_OP_REAL) and call
> vfs_getattr(&path, &stat, STATX_MTIME | STATX_CTIME, AT_STATX_SYNC_AS_STAT)
> to get the really real inode times also for directory.
> 
> But I think that would be considered a hack and the proper way to solve this
> would be to introduce a new dentry op ->d_real_inode().
> Unlike d_real_inode() which returns the inode used for open,
> ->d_real_inode() would return the inode used for stat.
> 
> If the helper d_real_inode() would call the new op,
> the only other user of d_real_inode() (check_conflicting_open) would have to
> open code inode_is_open_for_write(d_real(dentry)->d_inode)

Better just use the already existing ->d_real() with a special flags value to
indicate we want the real dentry for stat, not for open.

Something like this:

diff --git a/fs/inode.c b/fs/inode.c
index 50370599e371..8e526c7a1173 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1570,7 +1570,7 @@ static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
 			       bool rcu)
 {
 	if (!rcu) {
-		struct inode *realinode = d_real_inode(dentry);
+		struct inode *realinode = d_inode(d_real(dentry, NULL, -1));
 
 		if (unlikely(inode != realinode) &&
 		    (!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index d86e89f97201..792dc043f7b4 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -76,6 +76,10 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
 	int err;
 
 	if (!d_is_reg(dentry)) {
+		/* Special case -1 to mean query for stat not for open */
+		BUILD_BUG_ON((unsigned int) -1 ==  VALID_OPEN_FLAGS);
+		if (open_flags == (unsigned int) -1)
+			return ovl_dentry_real(dentry);
 		if (!inode || inode == d_inode(dentry))
 			return dentry;
 		goto bug;
--
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