ovl: copy up times
authorMiklos Szeredi <mszeredi@redhat.com>
Wed, 18 Jul 2018 13:44:40 +0000 (15:44 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Wed, 18 Jul 2018 13:44:40 +0000 (15:44 +0200)
Copy up mtime and ctime to overlay inode after times in real object are
modified.  Be careful not to dirty cachelines when not necessary.

This is in preparation for moving overlay functionality out of the VFS.

This patch shouldn't have any observable effect.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/overlayfs/util.c

index f480b1a2cd2e5ada2a7a3c978b00d541839b635a..4fa756c1b1900769bd639f3cbf832a96df30f53a 100644 (file)
@@ -242,7 +242,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
                .newinode = inode,
        };
 
-       ovl_dentry_version_inc(dentry->d_parent, false);
+       ovl_dir_modified(dentry->d_parent, false);
        ovl_dentry_set_upper_alias(dentry);
        if (!hardlink) {
                /*
@@ -722,7 +722,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
        if (err)
                goto out_d_drop;
 
-       ovl_dentry_version_inc(dentry->d_parent, true);
+       ovl_dir_modified(dentry->d_parent, true);
 out_d_drop:
        d_drop(dentry);
 out_dput_upper:
@@ -767,7 +767,7 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir,
                err = vfs_rmdir(dir, upper);
        else
                err = vfs_unlink(dir, upper, NULL);
-       ovl_dentry_version_inc(dentry->d_parent, ovl_type_origin(dentry));
+       ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry));
 
        /*
         * Keeping this dentry hashed would mean having to release
@@ -797,6 +797,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
        int err;
        bool locked = false;
        const struct cred *old_cred;
+       struct dentry *upperdentry;
        bool lower_positive = ovl_lower_positive(dentry);
        LIST_HEAD(list);
 
@@ -832,6 +833,17 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
                        drop_nlink(dentry->d_inode);
        }
        ovl_nlink_end(dentry, locked);
+
+       /*
+        * Copy ctime
+        *
+        * Note: we fail to update ctime if there was no copy-up, only a
+        * whiteout
+        */
+       upperdentry = ovl_dentry_upper(dentry);
+       if (upperdentry)
+               ovl_copyattr(d_inode(upperdentry), d_inode(dentry));
+
 out_drop_write:
        ovl_drop_write(dentry);
 out:
@@ -1138,10 +1150,15 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
                        drop_nlink(d_inode(new));
        }
 
-       ovl_dentry_version_inc(old->d_parent, ovl_type_origin(old) ||
-                              (!overwrite && ovl_type_origin(new)));
-       ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old) ||
-                              (d_inode(new) && ovl_type_origin(new)));
+       ovl_dir_modified(old->d_parent, ovl_type_origin(old) ||
+                        (!overwrite && ovl_type_origin(new)));
+       ovl_dir_modified(new->d_parent, ovl_type_origin(old) ||
+                        (d_inode(new) && ovl_type_origin(new)));
+
+       /* copy ctime: */
+       ovl_copyattr(d_inode(olddentry), d_inode(old));
+       if (d_inode(new) && ovl_dentry_upper(new))
+               ovl_copyattr(d_inode(newdentry), d_inode(new));
 
 out_dput:
        dput(newdentry);
index ed16a898caeb8d59ef3daad075c96774a7648db7..0fa48d5644e2a99f13744c3c0cc65d8965747e1a 100644 (file)
@@ -304,6 +304,9 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
        }
        revert_creds(old_cred);
 
+       /* copy c/mtime */
+       ovl_copyattr(d_inode(realdentry), inode);
+
 out_drop_write:
        ovl_drop_write(dentry);
 out:
index 7538b9b56237b46f6cb3f8ed00dc36cecd4b5c94..008420e834d877c39c4c58048f468cb44bdd7e2e 100644 (file)
@@ -231,7 +231,7 @@ void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
 void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
                    struct dentry *lowerdentry);
 void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
-void ovl_dentry_version_inc(struct dentry *dentry, bool impurity);
+void ovl_dir_modified(struct dentry *dentry, bool impurity);
 u64 ovl_dentry_version_get(struct dentry *dentry);
 bool ovl_is_whiteout(struct dentry *dentry);
 struct file *ovl_path_open(struct path *path, int flags);
index 6f1078028c66b4aced7c94f04959a754b293645c..30a05d1d679d6f79fdfaddaac38cbfead7be27f4 100644 (file)
@@ -333,7 +333,7 @@ void ovl_inode_update(struct inode *inode, struct dentry *upperdentry)
        }
 }
 
-void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
+static void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
 {
        struct inode *inode = d_inode(dentry);
 
@@ -348,6 +348,14 @@ void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
                OVL_I(inode)->version++;
 }
 
+void ovl_dir_modified(struct dentry *dentry, bool impurity)
+{
+       /* Copy mtime/ctime */
+       ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry));
+
+       ovl_dentry_version_inc(dentry, impurity);
+}
+
 u64 ovl_dentry_version_get(struct dentry *dentry)
 {
        struct inode *inode = d_inode(dentry);