ufs: don't touch mtime/ctime of directory being moved
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 16 Jun 2015 05:56:23 +0000 (01:56 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 16 Jun 2015 06:08:34 +0000 (02:08 -0400)
See "ext2: Do not update mtime of a moved directory" (and followup in
"ext2: fix unbalanced kmap()/kunmap()") for background; this is UFS
equivalent - the same problem exists here.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ufs/dir.c
fs/ufs/namei.c
fs/ufs/ufs.h

index 1bfe8cabff0f660d107c6bc97446a0cceaf940eb..862d284d438e8ece7bd6026aa908ea5a8adfb4de 100644 (file)
@@ -87,7 +87,8 @@ ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr)
 
 /* Releases the page */
 void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
-                 struct page *page, struct inode *inode)
+                 struct page *page, struct inode *inode,
+                 bool update_times)
 {
        loff_t pos = page_offset(page) +
                        (char *) de - (char *) page_address(page);
@@ -103,7 +104,8 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
 
        err = ufs_commit_chunk(page, pos, len);
        ufs_put_page(page);
-       dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+       if (update_times)
+               dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(dir);
 }
 
index 3429079c11e294b921e268876f25f12244f44cdf..d3fdfa22add58f6f50cd076f8937ad125a46e2f5 100644 (file)
@@ -276,7 +276,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
                new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
                if (!new_de)
                        goto out_dir;
-               ufs_set_link(new_dir, new_de, new_page, old_inode);
+               ufs_set_link(new_dir, new_de, new_page, old_inode, 1);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
                        drop_nlink(new_inode);
@@ -299,7 +299,12 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
        mark_inode_dirty(old_inode);
 
        if (dir_de) {
-               ufs_set_link(old_inode, dir_de, dir_page, new_dir);
+               if (old_dir != new_dir)
+                       ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0);
+               else {
+                       kunmap(dir_page);
+                       page_cache_release(dir_page);
+               }
                inode_dec_link_count(old_dir);
        }
        return 0;
index cf6368d42d4ab87ca6cbab4bb4da9205c8b5869a..2e31ea2e35a3b9bee06af97f03aa553d6f65082c 100644 (file)
@@ -106,7 +106,7 @@ extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page
 extern int ufs_empty_dir (struct inode *);
 extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
 extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
-                        struct page *page, struct inode *inode);
+                        struct page *page, struct inode *inode, bool update_times);
 
 /* file.c */
 extern const struct inode_operations ufs_file_inode_operations;