[JFFS2] Fix JFFS2 [mc]time handling
authorArtem B. Bityutskiy <dedekind@infradead.org>
Wed, 17 Aug 2005 13:46:26 +0000 (14:46 +0100)
committerThomas Gleixner <tglx@mtd.linutronix.de>
Sun, 6 Nov 2005 19:25:59 +0000 (20:25 +0100)
From: David Woodhouse <dwmw2@infradead.org>

Signed-off-by: Artem B. Bityutskiy <dedekind@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

fs/jffs2/dir.c
fs/jffs2/gc.c
fs/jffs2/nodelist.h
fs/jffs2/readinode.c
fs/jffs2/write.c

index 5738df2..0fd15aa 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $
+ * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $
  *
  */
 
@@ -232,11 +232,14 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
        struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode);
        int ret;
+       uint32_t now = get_seconds();
 
        ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 
-                              dentry->d_name.len, dead_f);
+                             dentry->d_name.len, dead_f, now);
        if (dead_f->inocache)
                dentry->d_inode->i_nlink = dead_f->inocache->nlink;
+       if (!ret)
+               dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
        return ret;
 }
 /***********************************************************************/
@@ -249,6 +252,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
        int ret;
        uint8_t type;
+       uint32_t now;
 
        /* Don't let people make hard links to bad inodes. */
        if (!f->inocache)
@@ -261,13 +265,15 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
        type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
        if (!type) type = DT_REG;
 
-       ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len);
+       now = get_seconds();
+       ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
 
        if (!ret) {
                down(&f->sem);
                old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
                up(&f->sem);
                d_instantiate(dentry, old_dentry->d_inode);
+               dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
                atomic_inc(&old_dentry->d_inode->i_count);
        }
        return ret;
@@ -716,6 +722,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
        struct jffs2_inode_info *victim_f = NULL;
        uint8_t type;
+       uint32_t now;
 
        /* The VFS will check for us and prevent trying to rename a 
         * file over a directory and vice versa, but if it's a directory,
@@ -749,9 +756,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
        if (!type) type = DT_REG;
 
+       now = get_seconds();
        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), 
                            old_dentry->d_inode->i_ino, type,
-                           new_dentry->d_name.name, new_dentry->d_name.len);
+                           new_dentry->d_name.name, new_dentry->d_name.len, now);
 
        if (ret)
                return ret;
@@ -775,7 +783,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 
        /* Unlink the original */
        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), 
-                     old_dentry->d_name.name, old_dentry->d_name.len, NULL);
+                             old_dentry->d_name.name, old_dentry->d_name.len, NULL, now);
 
        /* We don't touch inode->i_nlink */
 
@@ -792,12 +800,15 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                /* Might as well let the VFS know */
                d_instantiate(new_dentry, old_dentry->d_inode);
                atomic_inc(&old_dentry->d_inode->i_count);
+               new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
                return ret;
        }
 
        if (S_ISDIR(old_dentry->d_inode->i_mode))
                old_dir_i->i_nlink--;
 
+       new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
+
        return 0;
 }
 
index 362cfee..def9715 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $
+ * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $
  *
  */
 
@@ -771,7 +771,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
        rd.pino = cpu_to_je32(f->inocache->ino);
        rd.version = cpu_to_je32(++f->highest_version);
        rd.ino = cpu_to_je32(fd->ino);
-       rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f)));
+       /* If the times on this inode were set by explicit utime() they can be different,
+          so refrain from splatting them. */
+       if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f))
+               rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f));
+       else 
+               rd.mctime = cpu_to_je32(0);
        rd.type = fd->type;
        rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
        rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
@@ -883,6 +888,9 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
                kfree(rd);
        }
 
+       /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, 
+          we should update the metadata node with those times accordingly */
+
        /* No need for it any more. Just mark it obsolete and remove it from the list */
        while (*fdp) {
                if ((*fdp) == fd) {
index adee3c6..ce47d55 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodelist.h,v 1.137 2005/08/01 12:05:19 dedekind Exp $
+ * $Id: nodelist.h,v 1.138 2005/08/17 13:46:23 dedekind Exp $
  *
  */
 
@@ -336,8 +336,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                            struct jffs2_raw_inode *ri, unsigned char *buf, 
                            uint32_t offset, uint32_t writelen, uint32_t *retlen);
 int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen);
-int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f);
-int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen);
+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time);
 
 
 /* readinode.c */
index 50a62dd..6d5adab 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: readinode.c,v 1.139 2005/08/04 11:41:31 dedekind Exp $
+ * $Id: readinode.c,v 1.140 2005/08/17 13:46:23 dedekind Exp $
  *
  */
 
@@ -139,7 +139,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
        fd->type = rd->type;
 
        /* Pick out the mctime of the latest dirent */
-       if(fd->version > *mctime_ver) {
+       if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
                *mctime_ver = fd->version;
                *latest_mctime = je32_to_cpu(rd->mctime);
        }
index 4c418e6..0a19475 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $
+ * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $
  *
  */
 
@@ -533,7 +533,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
 
 
 int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
-                   const char *name, int namelen, struct jffs2_inode_info *dead_f)
+                   const char *name, int namelen, struct jffs2_inode_info *dead_f,
+                   uint32_t time)
 {
        struct jffs2_raw_dirent *rd;
        struct jffs2_full_dirent *fd;
@@ -565,7 +566,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
                rd->pino = cpu_to_je32(dir_f->inocache->ino);
                rd->version = cpu_to_je32(++dir_f->highest_version);
                rd->ino = cpu_to_je32(0);
-               rd->mctime = cpu_to_je32(get_seconds());
+               rd->mctime = cpu_to_je32(time);
                rd->nsize = namelen;
                rd->type = DT_UNKNOWN;
                rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
@@ -646,7 +647,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 }
 
 
-int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen)
+int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time)
 {
        struct jffs2_raw_dirent *rd;
        struct jffs2_full_dirent *fd;
@@ -674,7 +675,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
        rd->pino = cpu_to_je32(dir_f->inocache->ino);
        rd->version = cpu_to_je32(++dir_f->highest_version);
        rd->ino = cpu_to_je32(ino);
-       rd->mctime = cpu_to_je32(get_seconds());
+       rd->mctime = cpu_to_je32(time);
        rd->nsize = namelen;
 
        rd->type = type;